source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ bab75df6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since bab75df6 was bab75df6, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Let kernel code get printf via the standard stdio header. Clean up unused includes.

  • Property mode set to 100644
File size: 26.6 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Vana
3 * Copyright (c) 2012 Martin Decky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup kernel_generic
31 * @{
32 */
33/** @file
34 */
35
36#include <assert.h>
37#include <sysinfo/sysinfo.h>
38#include <mm/slab.h>
39#include <stdio.h>
40#include <syscall/copy.h>
41#include <synch/mutex.h>
42#include <arch/asm.h>
43#include <errno.h>
44#include <macros.h>
45
46/** Maximal sysinfo path length */
47#define SYSINFO_MAX_PATH 2048
48
49bool fb_exported = false;
50
51/** Global sysinfo tree root item */
52static sysinfo_item_t *global_root = NULL;
53
54/** Sysinfo SLAB cache */
55static slab_cache_t *sysinfo_item_cache;
56
57/** Sysinfo lock */
58static mutex_t sysinfo_lock;
59
60/** Sysinfo item constructor
61 *
62 */
63NO_TRACE static errno_t sysinfo_item_constructor(void *obj, unsigned int kmflag)
64{
65 sysinfo_item_t *item = (sysinfo_item_t *) obj;
66
67 item->name = NULL;
68 item->val_type = SYSINFO_VAL_UNDEFINED;
69 item->subtree_type = SYSINFO_SUBTREE_NONE;
70 item->subtree.table = NULL;
71 item->next = NULL;
72
73 return EOK;
74}
75
76/** Sysinfo item destructor
77 *
78 * Note that the return value is not perfectly correct
79 * since more space might get actually freed thanks
80 * to the disposal of item->name
81 *
82 */
83NO_TRACE static size_t sysinfo_item_destructor(void *obj)
84{
85 sysinfo_item_t *item = (sysinfo_item_t *) obj;
86
87 if (item->name != NULL)
88 free(item->name);
89
90 return 0;
91}
92
93/** Initialize sysinfo subsystem
94 *
95 * Create SLAB cache for sysinfo items.
96 *
97 */
98void sysinfo_init(void)
99{
100 sysinfo_item_cache = slab_cache_create("sysinfo_item_t",
101 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
102 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
103
104 mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE);
105}
106
107/** Recursively find an item in sysinfo tree
108 *
109 * Should be called with sysinfo_lock held.
110 *
111 * @param name Current sysinfo path suffix.
112 * @param subtree Current sysinfo (sub)tree root item.
113 * @param ret If the return value is NULL, this argument
114 * can be set either to NULL (i.e. no item was
115 * found and no data was generated) or the
116 * original pointer is used to store the value
117 * generated by a generated subtree function.
118 * @param dry_run Do not actually get any generated
119 * binary data, just calculate the size.
120 *
121 * @return Found item or NULL if no item in the fixed tree
122 * was found (N.B. ret).
123 *
124 */
125NO_TRACE static sysinfo_item_t *sysinfo_find_item(const char *name,
126 sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run)
127{
128 assert(subtree != NULL);
129
130 sysinfo_item_t *cur = subtree;
131
132 /* Walk all siblings */
133 while (cur != NULL) {
134 size_t i = 0;
135
136 /* Compare name with path */
137 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
138 i++;
139
140 /* Check for perfect name and path match */
141 if ((name[i] == 0) && (cur->name[i] == 0))
142 return cur;
143
144 /* Partial match up to the delimiter */
145 if ((name[i] == '.') && (cur->name[i] == 0)) {
146 /* Look into the subtree */
147 switch (cur->subtree_type) {
148 case SYSINFO_SUBTREE_TABLE:
149 /* Recursively find in subtree */
150 return sysinfo_find_item(name + i + 1,
151 cur->subtree.table, ret, dry_run);
152 case SYSINFO_SUBTREE_FUNCTION:
153 /* Get generated data */
154 if (ret != NULL)
155 **ret = cur->subtree.generator.fn(name + i + 1,
156 dry_run, cur->subtree.generator.data);
157
158 return NULL;
159 default:
160 /* Not found, no data generated */
161 if (ret != NULL)
162 *ret = NULL;
163
164 return NULL;
165 }
166 }
167
168 cur = cur->next;
169 }
170
171 /* Not found, no data generated */
172 if (ret != NULL)
173 *ret = NULL;
174
175 return NULL;
176}
177
178/** Recursively create items in sysinfo tree
179 *
180 * Should be called with sysinfo_lock held.
181 *
182 * @param name Current sysinfo path suffix.
183 * @param psubtree Pointer to an already existing (sub)tree root
184 * item or where to store a new tree root item.
185 *
186 * @return Existing or newly allocated sysinfo item or NULL
187 * if the current tree configuration does not allow to
188 * create a new item.
189 *
190 */
191NO_TRACE static sysinfo_item_t *sysinfo_create_path(const char *name,
192 sysinfo_item_t **psubtree)
193{
194 assert(psubtree != NULL);
195
196 if (*psubtree == NULL) {
197 /* No parent */
198
199 size_t i = 0;
200
201 /* Find the first delimiter in name */
202 while ((name[i] != 0) && (name[i] != '.'))
203 i++;
204
205 *psubtree =
206 (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
207 assert(*psubtree);
208
209 /* Fill in item name up to the delimiter */
210 (*psubtree)->name = str_ndup(name, i);
211 assert((*psubtree)->name);
212
213 /* Create subtree items */
214 if (name[i] == '.') {
215 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
216 return sysinfo_create_path(name + i + 1,
217 &((*psubtree)->subtree.table));
218 }
219
220 /* No subtree needs to be created */
221 return *psubtree;
222 }
223
224 sysinfo_item_t *cur = *psubtree;
225
226 /* Walk all siblings */
227 while (cur != NULL) {
228 size_t i = 0;
229
230 /* Compare name with path */
231 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
232 i++;
233
234 /*
235 * Check for perfect name and path match
236 * -> item is already present.
237 */
238 if ((name[i] == 0) && (cur->name[i] == 0))
239 return cur;
240
241 /* Partial match up to the delimiter */
242 if ((name[i] == '.') && (cur->name[i] == 0)) {
243 switch (cur->subtree_type) {
244 case SYSINFO_SUBTREE_NONE:
245 /* No subtree yet, create one */
246 cur->subtree_type = SYSINFO_SUBTREE_TABLE;
247 return sysinfo_create_path(name + i + 1,
248 &(cur->subtree.table));
249 case SYSINFO_SUBTREE_TABLE:
250 /* Subtree already created, add new sibling */
251 return sysinfo_create_path(name + i + 1,
252 &(cur->subtree.table));
253 default:
254 /*
255 * Subtree items handled by a function, this
256 * cannot be overriden by a constant item.
257 */
258 return NULL;
259 }
260 }
261
262 /*
263 * No match and no more siblings to check
264 * -> create a new sibling item.
265 */
266 if (cur->next == NULL) {
267 /* Find the first delimiter in name */
268 i = 0;
269 while ((name[i] != 0) && (name[i] != '.'))
270 i++;
271
272 sysinfo_item_t *item =
273 (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
274 assert(item);
275
276 cur->next = item;
277
278 /* Fill in item name up to the delimiter */
279 item->name = str_ndup(name, i);
280 assert(item->name);
281
282 /* Create subtree items */
283 if (name[i] == '.') {
284 item->subtree_type = SYSINFO_SUBTREE_TABLE;
285 return sysinfo_create_path(name + i + 1,
286 &(item->subtree.table));
287 }
288
289 /* No subtree needs to be created */
290 return item;
291 }
292
293 cur = cur->next;
294 }
295
296 /* Unreachable */
297 assert(false);
298 return NULL;
299}
300
301/** Set sysinfo item with a constant numeric value
302 *
303 * @param name Sysinfo path.
304 * @param root Pointer to the root item or where to store
305 * a new root item (NULL for global sysinfo root).
306 * @param val Value to store in the item.
307 *
308 */
309void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
310 sysarg_t val)
311{
312 /* Protect sysinfo tree consistency */
313 mutex_lock(&sysinfo_lock);
314
315 if (root == NULL)
316 root = &global_root;
317
318 sysinfo_item_t *item = sysinfo_create_path(name, root);
319 if (item != NULL) {
320 item->val_type = SYSINFO_VAL_VAL;
321 item->val.val = val;
322 }
323
324 mutex_unlock(&sysinfo_lock);
325}
326
327/** Set sysinfo item with a constant binary data
328 *
329 * Note that sysinfo only stores the pointer to the
330 * binary data and does not touch it in any way. The
331 * data should be static and immortal.
332 *
333 * @param name Sysinfo path.
334 * @param root Pointer to the root item or where to store
335 * a new root item (NULL for global sysinfo root).
336 * @param data Binary data.
337 * @param size Size of the binary data.
338 *
339 */
340void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
341 void *data, size_t size)
342{
343 /* Protect sysinfo tree consistency */
344 mutex_lock(&sysinfo_lock);
345
346 if (root == NULL)
347 root = &global_root;
348
349 sysinfo_item_t *item = sysinfo_create_path(name, root);
350 if (item != NULL) {
351 item->val_type = SYSINFO_VAL_DATA;
352 item->val.data.data = data;
353 item->val.data.size = size;
354 }
355
356 mutex_unlock(&sysinfo_lock);
357}
358
359/** Set sysinfo item with a generated numeric value
360 *
361 * @param name Sysinfo path.
362 * @param root Pointer to the root item or where to store
363 * a new root item (NULL for global sysinfo root).
364 * @param fn Numeric value generator function.
365 * @param data Private data.
366 *
367 */
368void sysinfo_set_item_gen_val(const char *name, sysinfo_item_t **root,
369 sysinfo_fn_val_t fn, void *data)
370{
371 /* Protect sysinfo tree consistency */
372 mutex_lock(&sysinfo_lock);
373
374 if (root == NULL)
375 root = &global_root;
376
377 sysinfo_item_t *item = sysinfo_create_path(name, root);
378 if (item != NULL) {
379 item->val_type = SYSINFO_VAL_FUNCTION_VAL;
380 item->val.gen_val.fn = fn;
381 item->val.gen_val.data = data;
382 }
383
384 mutex_unlock(&sysinfo_lock);
385}
386
387/** Set sysinfo item with a generated binary data
388 *
389 * Note that each time the generator function is called
390 * it is supposed to return a new dynamically allocated
391 * data. This data is then freed by sysinfo in the context
392 * of the current sysinfo request.
393 *
394 * @param name Sysinfo path.
395 * @param root Pointer to the root item or where to store
396 * a new root item (NULL for global sysinfo root).
397 * @param fn Binary data generator function.
398 * @param data Private data.
399 *
400 */
401void sysinfo_set_item_gen_data(const char *name, sysinfo_item_t **root,
402 sysinfo_fn_data_t fn, void *data)
403{
404 /* Protect sysinfo tree consistency */
405 mutex_lock(&sysinfo_lock);
406
407 if (root == NULL)
408 root = &global_root;
409
410 sysinfo_item_t *item = sysinfo_create_path(name, root);
411 if (item != NULL) {
412 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
413 item->val.gen_data.fn = fn;
414 item->val.gen_data.data = data;
415 }
416
417 mutex_unlock(&sysinfo_lock);
418}
419
420/** Set sysinfo item with an undefined value
421 *
422 * @param name Sysinfo path.
423 * @param root Pointer to the root item or where to store
424 * a new root item (NULL for global sysinfo root).
425 *
426 */
427void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
428{
429 /* Protect sysinfo tree consistency */
430 mutex_lock(&sysinfo_lock);
431
432 if (root == NULL)
433 root = &global_root;
434
435 sysinfo_item_t *item = sysinfo_create_path(name, root);
436 if (item != NULL)
437 item->val_type = SYSINFO_VAL_UNDEFINED;
438
439 mutex_unlock(&sysinfo_lock);
440}
441
442/** Set sysinfo item with a generated subtree
443 *
444 * @param name Sysinfo path.
445 * @param root Pointer to the root item or where to store
446 * a new root item (NULL for global sysinfo root).
447 * @param fn Subtree generator function.
448 * @param data Private data to be passed to the generator.
449 *
450 */
451void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
452 sysinfo_fn_subtree_t fn, void *data)
453{
454 /* Protect sysinfo tree consistency */
455 mutex_lock(&sysinfo_lock);
456
457 if (root == NULL)
458 root = &global_root;
459
460 sysinfo_item_t *item = sysinfo_create_path(name, root);
461
462 /*
463 * Change the type of the subtree only if it is not already
464 * a fixed subtree
465 */
466 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
467 item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
468 item->subtree.generator.fn = fn;
469 item->subtree.generator.data = data;
470 }
471
472 mutex_unlock(&sysinfo_lock);
473}
474
475/** Sysinfo dump indentation helper routine
476 *
477 * @param depth Number of spaces to print.
478 *
479 */
480NO_TRACE static void sysinfo_indent(size_t spaces)
481{
482 for (size_t i = 0; i < spaces; i++)
483 printf(" ");
484}
485
486/** Dump the structure of sysinfo tree
487 *
488 * Should be called with sysinfo_lock held.
489 *
490 * @param root Root item of the current (sub)tree.
491 * @param spaces Current indentation level.
492 *
493 */
494NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, size_t spaces)
495{
496 /* Walk all siblings */
497 for (sysinfo_item_t *cur = root; cur; cur = cur->next) {
498 size_t length;
499
500 if (spaces == 0) {
501 printf("%s", cur->name);
502 length = str_length(cur->name);
503 } else {
504 sysinfo_indent(spaces);
505 printf(".%s", cur->name);
506 length = str_length(cur->name) + 1;
507 }
508
509 sysarg_t val;
510 size_t size;
511
512 /* Display node value and type */
513 switch (cur->val_type) {
514 case SYSINFO_VAL_UNDEFINED:
515 printf(" [undefined]\n");
516 break;
517 case SYSINFO_VAL_VAL:
518 printf(" -> %" PRIun " (%#" PRIxn ")\n", cur->val.val,
519 cur->val.val);
520 break;
521 case SYSINFO_VAL_DATA:
522 printf(" (%zu bytes)\n", cur->val.data.size);
523 break;
524 case SYSINFO_VAL_FUNCTION_VAL:
525 val = cur->val.gen_val.fn(cur, cur->val.gen_val.data);
526 printf(" -> %" PRIun " (%#" PRIxn ") [generated]\n", val,
527 val);
528 break;
529 case SYSINFO_VAL_FUNCTION_DATA:
530 /* N.B.: No data was actually returned (only a dry run) */
531 (void) cur->val.gen_data.fn(cur, &size, true,
532 cur->val.gen_data.data);
533 printf(" (%zu bytes) [generated]\n", size);
534 break;
535 default:
536 printf("+ %s [unknown]\n", cur->name);
537 }
538
539 /* Recursivelly nest into the subtree */
540 switch (cur->subtree_type) {
541 case SYSINFO_SUBTREE_NONE:
542 break;
543 case SYSINFO_SUBTREE_TABLE:
544 sysinfo_dump_internal(cur->subtree.table, spaces + length);
545 break;
546 case SYSINFO_SUBTREE_FUNCTION:
547 sysinfo_indent(spaces + length);
548 printf("<generated subtree>\n");
549 break;
550 default:
551 sysinfo_indent(spaces + length);
552 printf("<unknown subtree>\n");
553 }
554 }
555}
556
557/** Dump the structure of sysinfo tree
558 *
559 * @param root Root item of the sysinfo (sub)tree.
560 * If it is NULL then consider the global
561 * sysinfo tree.
562 *
563 */
564void sysinfo_dump(sysinfo_item_t *root)
565{
566 /*
567 * Avoid other functions to mess with sysinfo
568 * while we are dumping it
569 */
570 mutex_lock(&sysinfo_lock);
571
572 if (root == NULL)
573 sysinfo_dump_internal(global_root, 0);
574 else
575 sysinfo_dump_internal(root, 0);
576
577 mutex_unlock(&sysinfo_lock);
578}
579
580/** Return sysinfo item value determined by name
581 *
582 * Should be called with sysinfo_lock held.
583 *
584 * @param name Sysinfo path.
585 * @param root Root item of the sysinfo (sub)tree.
586 * If it is NULL then consider the global
587 * sysinfo tree.
588 * @param dry_run Do not actually get any generated
589 * binary data, just calculate the size.
590 *
591 * @return Item value (constant or generated).
592 *
593 */
594NO_TRACE static sysinfo_return_t sysinfo_get_item(const char *name,
595 sysinfo_item_t **root, bool dry_run)
596{
597 if (root == NULL)
598 root = &global_root;
599
600 /* Try to find the item or generate data */
601 sysinfo_return_t ret;
602 sysinfo_return_t *ret_ptr = &ret;
603 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
604 dry_run);
605
606 if (item != NULL) {
607 /* Item found in the fixed sysinfo tree */
608
609 ret.tag = item->val_type;
610 switch (item->val_type) {
611 case SYSINFO_VAL_UNDEFINED:
612 break;
613 case SYSINFO_VAL_VAL:
614 ret.val = item->val.val;
615 break;
616 case SYSINFO_VAL_DATA:
617 ret.data = item->val.data;
618 break;
619 case SYSINFO_VAL_FUNCTION_VAL:
620 ret.val = item->val.gen_val.fn(item, item->val.gen_val.data);
621 break;
622 case SYSINFO_VAL_FUNCTION_DATA:
623 ret.data.data = item->val.gen_data.fn(item, &ret.data.size,
624 dry_run, item->val.gen_data.data);
625 break;
626 }
627 } else {
628 /* No item in the fixed sysinfo tree */
629 if (ret_ptr == NULL) {
630 /* Even no data was generated */
631 ret.tag = SYSINFO_VAL_UNDEFINED;
632 }
633 }
634
635 return ret;
636}
637
638/** Return sysinfo item determined by name from user space
639 *
640 * The path string passed from the user space has to be properly null-terminated
641 * (the last passed character must be null).
642 *
643 * @param ptr Sysinfo path in the user address space.
644 * @param size Size of the path string.
645 * @param dry_run Do not actually get any generated
646 * binary data, just calculate the size.
647 *
648 */
649NO_TRACE static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
650 bool dry_run)
651{
652 sysinfo_return_t ret;
653 ret.tag = SYSINFO_VAL_UNDEFINED;
654
655 if (size > SYSINFO_MAX_PATH)
656 return ret;
657
658 char *path = (char *) nfmalloc(size + 1);
659 assert(path);
660
661 if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
662 (path[size] == 0)) {
663 /*
664 * Prevent other functions from messing with sysinfo while we
665 * are reading it.
666 */
667 mutex_lock(&sysinfo_lock);
668 ret = sysinfo_get_item(path, NULL, dry_run);
669 mutex_unlock(&sysinfo_lock);
670 }
671
672 free(path);
673 return ret;
674}
675
676/** Return sysinfo keys determined by name
677 *
678 * Should be called with sysinfo_lock held.
679 *
680 * @param name Sysinfo path.
681 * @param root Root item of the sysinfo (sub)tree.
682 * If it is NULL then consider the global
683 * sysinfo tree.
684 * @param dry_run Do not actually get any generated
685 * binary data, just calculate the size.
686 *
687 * @return Item value (constant or generated).
688 *
689 */
690NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
691 sysinfo_item_t **root, bool dry_run)
692{
693 if (root == NULL)
694 root = &global_root;
695
696 sysinfo_item_t *subtree = NULL;
697
698 if (name[0] != 0) {
699 /* Try to find the item */
700 sysinfo_item_t *item =
701 sysinfo_find_item(name, *root, NULL, dry_run);
702 if ((item != NULL) &&
703 (item->subtree_type == SYSINFO_SUBTREE_TABLE))
704 subtree = item->subtree.table;
705 } else
706 subtree = *root;
707
708 sysinfo_return_t ret;
709 ret.tag = SYSINFO_VAL_UNDEFINED;
710
711 if (subtree != NULL) {
712 /*
713 * Calculate the size of subkeys.
714 */
715 size_t size = 0;
716 for (sysinfo_item_t *cur = subtree; cur; cur = cur->next)
717 size += str_size(cur->name) + 1;
718
719 if (dry_run) {
720 ret.tag = SYSINFO_VAL_DATA;
721 ret.data.data = NULL;
722 ret.data.size = size;
723 } else {
724 /* Allocate buffer for subkeys */
725 char *names = (char *) malloc(size);
726 if (names == NULL)
727 return ret;
728
729 size_t pos = 0;
730 for (sysinfo_item_t *cur = subtree; cur; cur = cur->next) {
731 str_cpy(names + pos, size - pos, cur->name);
732 pos += str_size(cur->name) + 1;
733 }
734
735 /* Correct return value */
736 ret.tag = SYSINFO_VAL_DATA;
737 ret.data.data = (void *) names;
738 ret.data.size = size;
739 }
740 }
741
742 return ret;
743}
744
745/** Return sysinfo keys determined by name from user space
746 *
747 * The path string passed from the user space has to be properly
748 * null-terminated (the last passed character must be null).
749 *
750 * @param ptr Sysinfo path in the user address space.
751 * @param size Size of the path string.
752 * @param dry_run Do not actually get any generated
753 * binary data, just calculate the size.
754 *
755 */
756NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
757 bool dry_run)
758{
759 sysinfo_return_t ret;
760 ret.tag = SYSINFO_VAL_UNDEFINED;
761 ret.data.data = NULL;
762 ret.data.size = 0;
763
764 if (size > SYSINFO_MAX_PATH)
765 return ret;
766
767 char *path = (char *) nfmalloc(size + 1);
768 assert(path);
769
770 if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
771 (path[size] == 0)) {
772 /*
773 * Prevent other functions from messing with sysinfo while we
774 * are reading it.
775 */
776 mutex_lock(&sysinfo_lock);
777 ret = sysinfo_get_keys(path, NULL, dry_run);
778 mutex_unlock(&sysinfo_lock);
779 }
780
781 free(path);
782 return ret;
783}
784
785/** Get the sysinfo keys size (syscall)
786 *
787 * The path string passed from the user space has
788 * to be properly null-terminated (the last passed
789 * character must be null).
790 *
791 * @param path_ptr Sysinfo path in the user address space.
792 * @param path_size Size of the path string.
793 * @param size_ptr User space pointer where to store the
794 * keys size.
795 *
796 * @return Error code (EOK in case of no error).
797 *
798 */
799sys_errno_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
800 void *size_ptr)
801{
802 errno_t rc;
803
804 /*
805 * Get the keys.
806 *
807 * N.B.: There is no need to free any potential keys
808 * since we request a dry run.
809 */
810 sysinfo_return_t ret =
811 sysinfo_get_keys_uspace(path_ptr, path_size, true);
812
813 /* Check return data tag */
814 if (ret.tag == SYSINFO_VAL_DATA)
815 rc = copy_to_uspace(size_ptr, &ret.data.size,
816 sizeof(ret.data.size));
817 else
818 rc = EINVAL;
819
820 return (sys_errno_t) rc;
821}
822
823/** Get the sysinfo keys (syscall)
824 *
825 * The path string passed from the user space has
826 * to be properly null-terminated (the last passed
827 * character must be null).
828 *
829 * If the user space buffer size does not equal
830 * the actual size of the returned data, the data
831 * is truncated.
832 *
833 * The actual size of data returned is stored to
834 * size_ptr.
835 *
836 * @param path_ptr Sysinfo path in the user address space.
837 * @param path_size Size of the path string.
838 * @param buffer_ptr User space pointer to the buffer where
839 * to store the binary data.
840 * @param buffer_size User space buffer size.
841 * @param size_ptr User space pointer where to store the
842 * binary data size.
843 *
844 * @return Error code (EOK in case of no error).
845 *
846 */
847sys_errno_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
848 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
849{
850 errno_t rc;
851
852 /* Get the keys */
853 sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
854 false);
855
856 /* Check return data tag */
857 if (ret.tag == SYSINFO_VAL_DATA) {
858 size_t size = min(ret.data.size, buffer_size);
859 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
860 if (rc == EOK)
861 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
862
863 free(ret.data.data);
864 } else
865 rc = EINVAL;
866
867 return (sys_errno_t) rc;
868}
869
870/** Get the sysinfo value type (syscall)
871 *
872 * The path string passed from the user space has
873 * to be properly null-terminated (the last passed
874 * character must be null).
875 *
876 * @param path_ptr Sysinfo path in the user address space.
877 * @param path_size Size of the path string.
878 *
879 * @return Item value type.
880 *
881 */
882sysarg_t sys_sysinfo_get_val_type(void *path_ptr, size_t path_size)
883{
884 /*
885 * Get the item.
886 *
887 * N.B.: There is no need to free any potential generated
888 * binary data since we request a dry run.
889 */
890 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
891
892 /*
893 * Map generated value types to constant types (user space does
894 * not care whether the value is constant or generated).
895 */
896 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
897 ret.tag = SYSINFO_VAL_VAL;
898 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
899 ret.tag = SYSINFO_VAL_DATA;
900
901 return (sysarg_t) ret.tag;
902}
903
904/** Get the sysinfo numerical value (syscall)
905 *
906 * The path string passed from the user space has
907 * to be properly null-terminated (the last passed
908 * character must be null).
909 *
910 * @param path_ptr Sysinfo path in the user address space.
911 * @param path_size Size of the path string.
912 * @param value_ptr User space pointer where to store the
913 * numberical value.
914 *
915 * @return Error code (EOK in case of no error).
916 *
917 */
918sys_errno_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
919 void *value_ptr)
920{
921 errno_t rc;
922
923 /*
924 * Get the item.
925 *
926 * N.B.: There is no need to free any potential generated binary
927 * data since we request a dry run.
928 */
929 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
930
931 /* Only constant or generated numerical value is returned */
932 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
933 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
934 else
935 rc = EINVAL;
936
937 return (sys_errno_t) rc;
938}
939
940/** Get the sysinfo binary data size (syscall)
941 *
942 * The path string passed from the user space has
943 * to be properly null-terminated (the last passed
944 * character must be null).
945 *
946 * @param path_ptr Sysinfo path in the user address space.
947 * @param path_size Size of the path string.
948 * @param size_ptr User space pointer where to store the
949 * binary data size.
950 *
951 * @return Error code (EOK in case of no error).
952 *
953 */
954sys_errno_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
955 void *size_ptr)
956{
957 errno_t rc;
958
959 /*
960 * Get the item.
961 *
962 * N.B.: There is no need to free any potential generated binary
963 * data since we request a dry run.
964 */
965 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
966
967 /* Only the size of constant or generated binary data is considered */
968 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
969 rc = copy_to_uspace(size_ptr, &ret.data.size,
970 sizeof(ret.data.size));
971 else
972 rc = EINVAL;
973
974 return (sys_errno_t) rc;
975}
976
977/** Get the sysinfo binary data (syscall)
978 *
979 * The path string passed from the user space has
980 * to be properly null-terminated (the last passed
981 * character must be null).
982 *
983 * If the user space buffer size does not equal
984 * the actual size of the returned data, the data
985 * is truncated. Whether this is actually a fatal
986 * error or the data can be still interpreted as valid
987 * depends on the nature of the data and has to be
988 * decided by the user space.
989 *
990 * The actual size of data returned is stored to
991 * size_ptr.
992 *
993 * @param path_ptr Sysinfo path in the user address space.
994 * @param path_size Size of the path string.
995 * @param buffer_ptr User space pointer to the buffer where
996 * to store the binary data.
997 * @param buffer_size User space buffer size.
998 * @param size_ptr User space pointer where to store the
999 * binary data size.
1000 *
1001 * @return Error code (EOK in case of no error).
1002 *
1003 */
1004sys_errno_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
1005 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
1006{
1007 errno_t rc;
1008
1009 /* Get the item */
1010 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size,
1011 false);
1012
1013 /* Only constant or generated binary data is considered */
1014 if ((ret.tag == SYSINFO_VAL_DATA) ||
1015 (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
1016 size_t size = min(ret.data.size, buffer_size);
1017 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
1018 if (rc == EOK)
1019 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
1020 } else
1021 rc = EINVAL;
1022
1023 /* N.B.: The generated binary data should be freed */
1024 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
1025 free(ret.data.data);
1026
1027 return (sys_errno_t) rc;
1028}
1029
1030/** @}
1031 */
Note: See TracBrowser for help on using the repository browser.