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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since efb8d15 was efb8d15, checked in by Martin Decky <martin@…>, 13 years ago

dump sysinfo in a more compact way

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