2 * Copyright (c) 2006 Jakub Vana
3 * Copyright (c) 2012 Martin Decky
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
30 /** @addtogroup generic
37 #include <sysinfo/sysinfo.h>
40 #include <syscall/copy.h>
41 #include <synch/mutex.h>
46 /** Maximal sysinfo path length */
47 #define SYSINFO_MAX_PATH 2048
49 bool fb_exported
= false;
51 /** Global sysinfo tree root item */
52 static sysinfo_item_t
*global_root
= NULL
;
54 /** Sysinfo SLAB cache */
55 static slab_cache_t
*sysinfo_item_slab
;
58 static mutex_t sysinfo_lock
;
60 /** Sysinfo item constructor
63 NO_TRACE
static int sysinfo_item_constructor(void *obj
, unsigned int kmflag
)
65 sysinfo_item_t
*item
= (sysinfo_item_t
*) obj
;
68 item
->val_type
= SYSINFO_VAL_UNDEFINED
;
69 item
->subtree_type
= SYSINFO_SUBTREE_NONE
;
70 item
->subtree
.table
= NULL
;
76 /** Sysinfo item destructor
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
83 NO_TRACE
static size_t sysinfo_item_destructor(void *obj
)
85 sysinfo_item_t
*item
= (sysinfo_item_t
*) obj
;
87 if (item
->name
!= NULL
)
93 /** Initialize sysinfo subsystem
95 * Create SLAB cache for sysinfo items.
98 void sysinfo_init(void)
100 sysinfo_item_slab
= slab_cache_create("sysinfo_item_t",
101 sizeof(sysinfo_item_t
), 0, sysinfo_item_constructor
,
102 sysinfo_item_destructor
, SLAB_CACHE_MAGDEFERRED
);
104 mutex_initialize(&sysinfo_lock
, MUTEX_ACTIVE
);
107 /** Recursively find an item in sysinfo tree
109 * Should be called with sysinfo_lock held.
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.
121 * @return Found item or NULL if no item in the fixed tree
122 * was found (N.B. ret).
125 NO_TRACE
static sysinfo_item_t
*sysinfo_find_item(const char *name
,
126 sysinfo_item_t
*subtree
, sysinfo_return_t
**ret
, bool dry_run
)
128 assert(subtree
!= NULL
);
130 sysinfo_item_t
*cur
= subtree
;
132 /* Walk all siblings */
133 while (cur
!= NULL
) {
136 /* Compare name with path */
137 while ((cur
->name
[i
] != 0) && (name
[i
] == cur
->name
[i
]))
140 /* Check for perfect name and path match */
141 if ((name
[i
] == 0) && (cur
->name
[i
] == 0))
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 */
155 **ret
= cur
->subtree
.generator
.fn(name
+ i
+ 1,
156 dry_run
, cur
->subtree
.generator
.data
);
160 /* Not found, no data generated */
171 /* Not found, no data generated */
178 /** Recursively create items in sysinfo tree
180 * Should be called with sysinfo_lock held.
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.
186 * @return Existing or newly allocated sysinfo item or NULL
187 * if the current tree configuration does not allow to
191 NO_TRACE
static sysinfo_item_t
*sysinfo_create_path(const char *name
,
192 sysinfo_item_t
**psubtree
)
194 assert(psubtree
!= NULL
);
196 if (*psubtree
== NULL
) {
201 /* Find the first delimiter in name */
202 while ((name
[i
] != 0) && (name
[i
] != '.'))
206 (sysinfo_item_t
*) slab_alloc(sysinfo_item_slab
, 0);
209 /* Fill in item name up to the delimiter */
210 (*psubtree
)->name
= str_ndup(name
, i
);
211 assert((*psubtree
)->name
);
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
));
220 /* No subtree needs to be created */
224 sysinfo_item_t
*cur
= *psubtree
;
226 /* Walk all siblings */
227 while (cur
!= NULL
) {
230 /* Compare name with path */
231 while ((cur
->name
[i
] != 0) && (name
[i
] == cur
->name
[i
]))
234 /* Check for perfect name and path match
235 * -> item is already present.
237 if ((name
[i
] == 0) && (cur
->name
[i
] == 0))
240 /* Partial match up to the delimiter */
241 if ((name
[i
] == '.') && (cur
->name
[i
] == 0)) {
242 switch (cur
->subtree_type
) {
243 case SYSINFO_SUBTREE_NONE
:
244 /* No subtree yet, create one */
245 cur
->subtree_type
= SYSINFO_SUBTREE_TABLE
;
246 return sysinfo_create_path(name
+ i
+ 1,
247 &(cur
->subtree
.table
));
248 case SYSINFO_SUBTREE_TABLE
:
249 /* Subtree already created, add new sibling */
250 return sysinfo_create_path(name
+ i
+ 1,
251 &(cur
->subtree
.table
));
253 /* Subtree items handled by a function, this
254 * cannot be overriden by a constant item.
260 /* No match and no more siblings to check
261 * -> create a new sibling item.
263 if (cur
->next
== NULL
) {
264 /* Find the first delimiter in name */
266 while ((name
[i
] != 0) && (name
[i
] != '.'))
269 sysinfo_item_t
*item
=
270 (sysinfo_item_t
*) slab_alloc(sysinfo_item_slab
, 0);
275 /* Fill in item name up to the delimiter */
276 item
->name
= str_ndup(name
, i
);
279 /* Create subtree items */
280 if (name
[i
] == '.') {
281 item
->subtree_type
= SYSINFO_SUBTREE_TABLE
;
282 return sysinfo_create_path(name
+ i
+ 1,
283 &(item
->subtree
.table
));
286 /* No subtree needs to be created */
298 /** Set sysinfo item with a constant numeric value
300 * @param name Sysinfo path.
301 * @param root Pointer to the root item or where to store
302 * a new root item (NULL for global sysinfo root).
303 * @param val Value to store in the item.
306 void sysinfo_set_item_val(const char *name
, sysinfo_item_t
**root
,
309 /* Protect sysinfo tree consistency */
310 mutex_lock(&sysinfo_lock
);
315 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
317 item
->val_type
= SYSINFO_VAL_VAL
;
321 mutex_unlock(&sysinfo_lock
);
324 /** Set sysinfo item with a constant binary data
326 * Note that sysinfo only stores the pointer to the
327 * binary data and does not touch it in any way. The
328 * data should be static and immortal.
330 * @param name Sysinfo path.
331 * @param root Pointer to the root item or where to store
332 * a new root item (NULL for global sysinfo root).
333 * @param data Binary data.
334 * @param size Size of the binary data.
337 void sysinfo_set_item_data(const char *name
, sysinfo_item_t
**root
,
338 void *data
, size_t size
)
340 /* Protect sysinfo tree consistency */
341 mutex_lock(&sysinfo_lock
);
346 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
348 item
->val_type
= SYSINFO_VAL_DATA
;
349 item
->val
.data
.data
= data
;
350 item
->val
.data
.size
= size
;
353 mutex_unlock(&sysinfo_lock
);
356 /** Set sysinfo item with a generated numeric value
358 * @param name Sysinfo path.
359 * @param root Pointer to the root item or where to store
360 * a new root item (NULL for global sysinfo root).
361 * @param fn Numeric value generator function.
362 * @param data Private data.
365 void sysinfo_set_item_gen_val(const char *name
, sysinfo_item_t
**root
,
366 sysinfo_fn_val_t fn
, void *data
)
368 /* Protect sysinfo tree consistency */
369 mutex_lock(&sysinfo_lock
);
374 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
376 item
->val_type
= SYSINFO_VAL_FUNCTION_VAL
;
377 item
->val
.gen_val
.fn
= fn
;
378 item
->val
.gen_val
.data
= data
;
381 mutex_unlock(&sysinfo_lock
);
384 /** Set sysinfo item with a generated binary data
386 * Note that each time the generator function is called
387 * it is supposed to return a new dynamically allocated
388 * data. This data is then freed by sysinfo in the context
389 * of the current sysinfo request.
391 * @param name Sysinfo path.
392 * @param root Pointer to the root item or where to store
393 * a new root item (NULL for global sysinfo root).
394 * @param fn Binary data generator function.
395 * @param data Private data.
398 void sysinfo_set_item_gen_data(const char *name
, sysinfo_item_t
**root
,
399 sysinfo_fn_data_t fn
, void *data
)
401 /* Protect sysinfo tree consistency */
402 mutex_lock(&sysinfo_lock
);
407 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
409 item
->val_type
= SYSINFO_VAL_FUNCTION_DATA
;
410 item
->val
.gen_data
.fn
= fn
;
411 item
->val
.gen_data
.data
= data
;
414 mutex_unlock(&sysinfo_lock
);
417 /** Set sysinfo item with an undefined value
419 * @param name Sysinfo path.
420 * @param root Pointer to the root item or where to store
421 * a new root item (NULL for global sysinfo root).
424 void sysinfo_set_item_undefined(const char *name
, sysinfo_item_t
**root
)
426 /* Protect sysinfo tree consistency */
427 mutex_lock(&sysinfo_lock
);
432 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
434 item
->val_type
= SYSINFO_VAL_UNDEFINED
;
436 mutex_unlock(&sysinfo_lock
);
439 /** Set sysinfo item with a generated subtree
441 * @param name Sysinfo path.
442 * @param root Pointer to the root item or where to store
443 * a new root item (NULL for global sysinfo root).
444 * @param fn Subtree generator function.
445 * @param data Private data to be passed to the generator.
448 void sysinfo_set_subtree_fn(const char *name
, sysinfo_item_t
**root
,
449 sysinfo_fn_subtree_t fn
, void *data
)
451 /* Protect sysinfo tree consistency */
452 mutex_lock(&sysinfo_lock
);
457 sysinfo_item_t
*item
= sysinfo_create_path(name
, root
);
459 /* Change the type of the subtree only if it is not already
461 if ((item
!= NULL
) && (item
->subtree_type
!= SYSINFO_SUBTREE_TABLE
)) {
462 item
->subtree_type
= SYSINFO_SUBTREE_FUNCTION
;
463 item
->subtree
.generator
.fn
= fn
;
464 item
->subtree
.generator
.data
= data
;
467 mutex_unlock(&sysinfo_lock
);
470 /** Sysinfo dump indentation helper routine
472 * @param depth Number of spaces to print.
475 NO_TRACE
static void sysinfo_indent(size_t spaces
)
477 for (size_t i
= 0; i
< spaces
; i
++)
481 /** Dump the structure of sysinfo tree
483 * Should be called with sysinfo_lock held.
485 * @param root Root item of the current (sub)tree.
486 * @param spaces Current indentation level.
489 NO_TRACE
static void sysinfo_dump_internal(sysinfo_item_t
*root
, size_t spaces
)
491 /* Walk all siblings */
492 for (sysinfo_item_t
*cur
= root
; cur
; cur
= cur
->next
) {
496 printf("%s", cur
->name
);
497 length
= str_length(cur
->name
);
499 sysinfo_indent(spaces
);
500 printf(".%s", cur
->name
);
501 length
= str_length(cur
->name
) + 1;
507 /* Display node value and type */
508 switch (cur
->val_type
) {
509 case SYSINFO_VAL_UNDEFINED
:
510 printf(" [undefined]\n");
512 case SYSINFO_VAL_VAL
:
513 printf(" -> %" PRIun
" (%#" PRIxn
")\n", cur
->val
.val
,
516 case SYSINFO_VAL_DATA
:
517 printf(" (%zu bytes)\n", cur
->val
.data
.size
);
519 case SYSINFO_VAL_FUNCTION_VAL
:
520 val
= cur
->val
.gen_val
.fn(cur
, cur
->val
.gen_val
.data
);
521 printf(" -> %" PRIun
" (%#" PRIxn
") [generated]\n", val
,
524 case SYSINFO_VAL_FUNCTION_DATA
:
525 /* N.B.: No data was actually returned (only a dry run) */
526 (void) cur
->val
.gen_data
.fn(cur
, &size
, true,
527 cur
->val
.gen_data
.data
);
528 printf(" (%zu bytes) [generated]\n", size
);
531 printf("+ %s [unknown]\n", cur
->name
);
534 /* Recursivelly nest into the subtree */
535 switch (cur
->subtree_type
) {
536 case SYSINFO_SUBTREE_NONE
:
538 case SYSINFO_SUBTREE_TABLE
:
539 sysinfo_dump_internal(cur
->subtree
.table
, spaces
+ length
);
541 case SYSINFO_SUBTREE_FUNCTION
:
542 sysinfo_indent(spaces
+ length
);
543 printf("<generated subtree>\n");
546 sysinfo_indent(spaces
+ length
);
547 printf("<unknown subtree>\n");
552 /** Dump the structure of sysinfo tree
554 * @param root Root item of the sysinfo (sub)tree.
555 * If it is NULL then consider the global
559 void sysinfo_dump(sysinfo_item_t
*root
)
561 /* Avoid other functions to mess with sysinfo
562 while we are dumping it */
563 mutex_lock(&sysinfo_lock
);
566 sysinfo_dump_internal(global_root
, 0);
568 sysinfo_dump_internal(root
, 0);
570 mutex_unlock(&sysinfo_lock
);
573 /** Return sysinfo item value determined by name
575 * Should be called with sysinfo_lock held.
577 * @param name Sysinfo path.
578 * @param root Root item of the sysinfo (sub)tree.
579 * If it is NULL then consider the global
581 * @param dry_run Do not actually get any generated
582 * binary data, just calculate the size.
584 * @return Item value (constant or generated).
587 NO_TRACE
static sysinfo_return_t
sysinfo_get_item(const char *name
,
588 sysinfo_item_t
**root
, bool dry_run
)
593 /* Try to find the item or generate data */
594 sysinfo_return_t ret
;
595 sysinfo_return_t
*ret_ptr
= &ret
;
596 sysinfo_item_t
*item
= sysinfo_find_item(name
, *root
, &ret_ptr
,
600 /* Item found in the fixed sysinfo tree */
602 ret
.tag
= item
->val_type
;
603 switch (item
->val_type
) {
604 case SYSINFO_VAL_UNDEFINED
:
606 case SYSINFO_VAL_VAL
:
607 ret
.val
= item
->val
.val
;
609 case SYSINFO_VAL_DATA
:
610 ret
.data
= item
->val
.data
;
612 case SYSINFO_VAL_FUNCTION_VAL
:
613 ret
.val
= item
->val
.gen_val
.fn(item
, item
->val
.gen_val
.data
);
615 case SYSINFO_VAL_FUNCTION_DATA
:
616 ret
.data
.data
= item
->val
.gen_data
.fn(item
, &ret
.data
.size
,
617 dry_run
, item
->val
.gen_data
.data
);
621 /* No item in the fixed sysinfo tree */
622 if (ret_ptr
== NULL
) {
623 /* Even no data was generated */
624 ret
.tag
= SYSINFO_VAL_UNDEFINED
;
631 /** Return sysinfo item determined by name from user space
633 * The path string passed from the user space has to be properly null-terminated
634 * (the last passed character must be null).
636 * @param ptr Sysinfo path in the user address space.
637 * @param size Size of the path string.
638 * @param dry_run Do not actually get any generated
639 * binary data, just calculate the size.
642 NO_TRACE
static sysinfo_return_t
sysinfo_get_item_uspace(void *ptr
, size_t size
,
645 sysinfo_return_t ret
;
646 ret
.tag
= SYSINFO_VAL_UNDEFINED
;
648 if (size
> SYSINFO_MAX_PATH
)
651 char *path
= (char *) malloc(size
+ 1, 0);
654 if ((copy_from_uspace(path
, ptr
, size
+ 1) == 0) &&
657 * Prevent other functions from messing with sysinfo while we
660 mutex_lock(&sysinfo_lock
);
661 ret
= sysinfo_get_item(path
, NULL
, dry_run
);
662 mutex_unlock(&sysinfo_lock
);
669 /** Return sysinfo keys determined by name
671 * Should be called with sysinfo_lock held.
673 * @param name Sysinfo path.
674 * @param root Root item of the sysinfo (sub)tree.
675 * If it is NULL then consider the global
677 * @param dry_run Do not actually get any generated
678 * binary data, just calculate the size.
680 * @return Item value (constant or generated).
683 NO_TRACE
static sysinfo_return_t
sysinfo_get_keys(const char *name
,
684 sysinfo_item_t
**root
, bool dry_run
)
689 sysinfo_item_t
*subtree
= NULL
;
692 /* Try to find the item */
693 sysinfo_item_t
*item
=
694 sysinfo_find_item(name
, *root
, NULL
, dry_run
);
695 if ((item
!= NULL
) &&
696 (item
->subtree_type
== SYSINFO_SUBTREE_TABLE
))
697 subtree
= item
->subtree
.table
;
701 sysinfo_return_t ret
;
702 ret
.tag
= SYSINFO_VAL_UNDEFINED
;
704 if (subtree
!= NULL
) {
706 * Calculate the size of subkeys.
709 for (sysinfo_item_t
*cur
= subtree
; cur
; cur
= cur
->next
)
710 size
+= str_size(cur
->name
) + 1;
713 ret
.tag
= SYSINFO_VAL_DATA
;
714 ret
.data
.data
= NULL
;
715 ret
.data
.size
= size
;
717 /* Allocate buffer for subkeys */
718 char *names
= (char *) malloc(size
, FRAME_ATOMIC
);
723 for (sysinfo_item_t
*cur
= subtree
; cur
; cur
= cur
->next
) {
724 str_cpy(names
+ pos
, size
- pos
, cur
->name
);
725 pos
+= str_size(cur
->name
) + 1;
728 /* Correct return value */
729 ret
.tag
= SYSINFO_VAL_DATA
;
730 ret
.data
.data
= (void *) names
;
731 ret
.data
.size
= size
;
738 /** Return sysinfo keys determined by name from user space
740 * The path string passed from the user space has to be properly
741 * null-terminated (the last passed character must be null).
743 * @param ptr Sysinfo path in the user address space.
744 * @param size Size of the path string.
745 * @param dry_run Do not actually get any generated
746 * binary data, just calculate the size.
749 NO_TRACE
static sysinfo_return_t
sysinfo_get_keys_uspace(void *ptr
, size_t size
,
752 sysinfo_return_t ret
;
753 ret
.tag
= SYSINFO_VAL_UNDEFINED
;
754 ret
.data
.data
= NULL
;
757 if (size
> SYSINFO_MAX_PATH
)
760 char *path
= (char *) malloc(size
+ 1, 0);
763 if ((copy_from_uspace(path
, ptr
, size
+ 1) == 0) &&
766 * Prevent other functions from messing with sysinfo while we
769 mutex_lock(&sysinfo_lock
);
770 ret
= sysinfo_get_keys(path
, NULL
, dry_run
);
771 mutex_unlock(&sysinfo_lock
);
778 /** Get the sysinfo keys size (syscall)
780 * The path string passed from the user space has
781 * to be properly null-terminated (the last passed
782 * character must be null).
784 * @param path_ptr Sysinfo path in the user address space.
785 * @param path_size Size of the path string.
786 * @param size_ptr User space pointer where to store the
789 * @return Error code (EOK in case of no error).
792 sysarg_t
sys_sysinfo_get_keys_size(void *path_ptr
, size_t path_size
,
800 * N.B.: There is no need to free any potential keys
801 * since we request a dry run.
803 sysinfo_return_t ret
=
804 sysinfo_get_keys_uspace(path_ptr
, path_size
, true);
806 /* Check return data tag */
807 if (ret
.tag
== SYSINFO_VAL_DATA
)
808 rc
= copy_to_uspace(size_ptr
, &ret
.data
.size
,
809 sizeof(ret
.data
.size
));
813 return (sysarg_t
) rc
;
816 /** Get the sysinfo keys (syscall)
818 * The path string passed from the user space has
819 * to be properly null-terminated (the last passed
820 * character must be null).
822 * If the user space buffer size does not equal
823 * the actual size of the returned data, the data
826 * The actual size of data returned is stored to
829 * @param path_ptr Sysinfo path in the user address space.
830 * @param path_size Size of the path string.
831 * @param buffer_ptr User space pointer to the buffer where
832 * to store the binary data.
833 * @param buffer_size User space buffer size.
834 * @param size_ptr User space pointer where to store the
837 * @return Error code (EOK in case of no error).
840 sysarg_t
sys_sysinfo_get_keys(void *path_ptr
, size_t path_size
,
841 void *buffer_ptr
, size_t buffer_size
, size_t *size_ptr
)
846 sysinfo_return_t ret
= sysinfo_get_keys_uspace(path_ptr
, path_size
,
849 /* Check return data tag */
850 if (ret
.tag
== SYSINFO_VAL_DATA
) {
851 size_t size
= min(ret
.data
.size
, buffer_size
);
852 rc
= copy_to_uspace(buffer_ptr
, ret
.data
.data
, size
);
854 rc
= copy_to_uspace(size_ptr
, &size
, sizeof(size
));
860 return (sysarg_t
) rc
;
863 /** Get the sysinfo value type (syscall)
865 * The path string passed from the user space has
866 * to be properly null-terminated (the last passed
867 * character must be null).
869 * @param path_ptr Sysinfo path in the user address space.
870 * @param path_size Size of the path string.
872 * @return Item value type.
875 sysarg_t
sys_sysinfo_get_val_type(void *path_ptr
, size_t path_size
)
880 * N.B.: There is no need to free any potential generated
881 * binary data since we request a dry run.
883 sysinfo_return_t ret
= sysinfo_get_item_uspace(path_ptr
, path_size
, true);
886 * Map generated value types to constant types (user space does
887 * not care whether the value is constant or generated).
889 if (ret
.tag
== SYSINFO_VAL_FUNCTION_VAL
)
890 ret
.tag
= SYSINFO_VAL_VAL
;
891 else if (ret
.tag
== SYSINFO_VAL_FUNCTION_DATA
)
892 ret
.tag
= SYSINFO_VAL_DATA
;
894 return (sysarg_t
) ret
.tag
;
897 /** Get the sysinfo numerical value (syscall)
899 * The path string passed from the user space has
900 * to be properly null-terminated (the last passed
901 * character must be null).
903 * @param path_ptr Sysinfo path in the user address space.
904 * @param path_size Size of the path string.
905 * @param value_ptr User space pointer where to store the
908 * @return Error code (EOK in case of no error).
911 sysarg_t
sys_sysinfo_get_value(void *path_ptr
, size_t path_size
,
919 * N.B.: There is no need to free any potential generated binary
920 * data since we request a dry run.
922 sysinfo_return_t ret
= sysinfo_get_item_uspace(path_ptr
, path_size
, true);
924 /* Only constant or generated numerical value is returned */
925 if ((ret
.tag
== SYSINFO_VAL_VAL
) || (ret
.tag
== SYSINFO_VAL_FUNCTION_VAL
))
926 rc
= copy_to_uspace(value_ptr
, &ret
.val
, sizeof(ret
.val
));
930 return (sysarg_t
) rc
;
933 /** Get the sysinfo binary data size (syscall)
935 * The path string passed from the user space has
936 * to be properly null-terminated (the last passed
937 * character must be null).
939 * @param path_ptr Sysinfo path in the user address space.
940 * @param path_size Size of the path string.
941 * @param size_ptr User space pointer where to store the
944 * @return Error code (EOK in case of no error).
947 sysarg_t
sys_sysinfo_get_data_size(void *path_ptr
, size_t path_size
,
955 * N.B.: There is no need to free any potential generated binary
956 * data since we request a dry run.
958 sysinfo_return_t ret
= sysinfo_get_item_uspace(path_ptr
, path_size
, true);
960 /* Only the size of constant or generated binary data is considered */
961 if ((ret
.tag
== SYSINFO_VAL_DATA
) || (ret
.tag
== SYSINFO_VAL_FUNCTION_DATA
))
962 rc
= copy_to_uspace(size_ptr
, &ret
.data
.size
,
963 sizeof(ret
.data
.size
));
967 return (sysarg_t
) rc
;
970 /** Get the sysinfo binary data (syscall)
972 * The path string passed from the user space has
973 * to be properly null-terminated (the last passed
974 * character must be null).
976 * If the user space buffer size does not equal
977 * the actual size of the returned data, the data
978 * is truncated. Whether this is actually a fatal
979 * error or the data can be still interpreted as valid
980 * depends on the nature of the data and has to be
981 * decided by the user space.
983 * The actual size of data returned is stored to
986 * @param path_ptr Sysinfo path in the user address space.
987 * @param path_size Size of the path string.
988 * @param buffer_ptr User space pointer to the buffer where
989 * to store the binary data.
990 * @param buffer_size User space buffer size.
991 * @param size_ptr User space pointer where to store the
994 * @return Error code (EOK in case of no error).
997 sysarg_t
sys_sysinfo_get_data(void *path_ptr
, size_t path_size
,
998 void *buffer_ptr
, size_t buffer_size
, size_t *size_ptr
)
1003 sysinfo_return_t ret
= sysinfo_get_item_uspace(path_ptr
, path_size
,
1006 /* Only constant or generated binary data is considered */
1007 if ((ret
.tag
== SYSINFO_VAL_DATA
) ||
1008 (ret
.tag
== SYSINFO_VAL_FUNCTION_DATA
)) {
1009 size_t size
= min(ret
.data
.size
, buffer_size
);
1010 rc
= copy_to_uspace(buffer_ptr
, ret
.data
.data
, size
);
1012 rc
= copy_to_uspace(size_ptr
, &size
, sizeof(size
));
1016 /* N.B.: The generated binary data should be freed */
1017 if ((ret
.tag
== SYSINFO_VAL_FUNCTION_DATA
) && (ret
.data
.data
!= NULL
))
1018 free(ret
.data
.data
);
1020 return (sysarg_t
) rc
;