source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ 0030eef

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

add kernel support for listing sysinfo keys from uspace

  • Property mode set to 100644
File size: 26.2 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 indentation characters to print.
467 *
468 */
469NO_TRACE static void sysinfo_indent(unsigned int depth)
470{
471 unsigned int i;
472 for (i = 0; i < depth; i++)
473 printf(" ");
474}
475
476/** Dump the structure of sysinfo tree
477 *
478 * Should be called with sysinfo_lock held.
479 *
480 * @param root Root item of the current (sub)tree.
481 * @param depth Current depth in the sysinfo tree.
482 *
483 */
484NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
485{
486 sysinfo_item_t *cur = root;
487
488 /* Walk all siblings */
489 while (cur != NULL) {
490 sysinfo_indent(depth);
491
492 sysarg_t val;
493 size_t size;
494
495 /* Display node value and type */
496 switch (cur->val_type) {
497 case SYSINFO_VAL_UNDEFINED:
498 printf("+ %s\n", cur->name);
499 break;
500 case SYSINFO_VAL_VAL:
501 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
502 cur->val.val, cur->val.val);
503 break;
504 case SYSINFO_VAL_DATA:
505 printf("+ %s (%zu bytes)\n", cur->name,
506 cur->val.data.size);
507 break;
508 case SYSINFO_VAL_FUNCTION_VAL:
509 val = cur->val.fn_val(cur);
510 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
511 cur->name, val, val);
512 break;
513 case SYSINFO_VAL_FUNCTION_DATA:
514 /* N.B.: No data was actually returned (only a dry run) */
515 (void) cur->val.fn_data(cur, &size, true);
516 printf("+ %s (%zu bytes) [generated]\n", cur->name,
517 size);
518 break;
519 default:
520 printf("+ %s [unknown]\n", cur->name);
521 }
522
523 /* Recursivelly nest into the subtree */
524 switch (cur->subtree_type) {
525 case SYSINFO_SUBTREE_NONE:
526 break;
527 case SYSINFO_SUBTREE_TABLE:
528 sysinfo_dump_internal(cur->subtree.table, depth + 1);
529 break;
530 case SYSINFO_SUBTREE_FUNCTION:
531 sysinfo_indent(depth + 1);
532 printf("+ [generated subtree]\n");
533 break;
534 default:
535 sysinfo_indent(depth + 1);
536 printf("+ [unknown subtree]\n");
537 }
538
539 cur = cur->next;
540 }
541}
542
543/** Dump the structure of sysinfo tree
544 *
545 * @param root Root item of the sysinfo (sub)tree.
546 * If it is NULL then consider the global
547 * sysinfo tree.
548 *
549 */
550void sysinfo_dump(sysinfo_item_t *root)
551{
552 /* Avoid other functions to mess with sysinfo
553 while we are dumping it */
554 mutex_lock(&sysinfo_lock);
555
556 if (root == NULL)
557 sysinfo_dump_internal(global_root, 0);
558 else
559 sysinfo_dump_internal(root, 0);
560
561 mutex_unlock(&sysinfo_lock);
562}
563
564/** Return sysinfo item value determined by name
565 *
566 * Should be called with sysinfo_lock held.
567 *
568 * @param name Sysinfo path.
569 * @param root Root item of the sysinfo (sub)tree.
570 * If it is NULL then consider the global
571 * sysinfo tree.
572 * @param dry_run Do not actually get any generated
573 * binary data, just calculate the size.
574 *
575 * @return Item value (constant or generated).
576 *
577 */
578NO_TRACE static sysinfo_return_t sysinfo_get_item(const char *name,
579 sysinfo_item_t **root, bool dry_run)
580{
581 if (root == NULL)
582 root = &global_root;
583
584 /* Try to find the item or generate data */
585 sysinfo_return_t ret;
586 sysinfo_return_t *ret_ptr = &ret;
587 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
588 dry_run);
589
590 if (item != NULL) {
591 /* Item found in the fixed sysinfo tree */
592
593 ret.tag = item->val_type;
594 switch (item->val_type) {
595 case SYSINFO_VAL_UNDEFINED:
596 break;
597 case SYSINFO_VAL_VAL:
598 ret.val = item->val.val;
599 break;
600 case SYSINFO_VAL_DATA:
601 ret.data = item->val.data;
602 break;
603 case SYSINFO_VAL_FUNCTION_VAL:
604 ret.val = item->val.fn_val(item);
605 break;
606 case SYSINFO_VAL_FUNCTION_DATA:
607 ret.data.data = item->val.fn_data(item, &ret.data.size,
608 dry_run);
609 break;
610 }
611 } else {
612 /* No item in the fixed sysinfo tree */
613 if (ret_ptr == NULL) {
614 /* Even no data was generated */
615 ret.tag = SYSINFO_VAL_UNDEFINED;
616 }
617 }
618
619 return ret;
620}
621
622/** Return sysinfo item determined by name from user space
623 *
624 * The path string passed from the user space has to be properly null-terminated
625 * (the last passed character must be null).
626 *
627 * @param ptr Sysinfo path in the user address space.
628 * @param size Size of the path string.
629 * @param dry_run Do not actually get any generated
630 * binary data, just calculate the size.
631 *
632 */
633NO_TRACE static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
634 bool dry_run)
635{
636 sysinfo_return_t ret;
637 ret.tag = SYSINFO_VAL_UNDEFINED;
638
639 if (size > SYSINFO_MAX_PATH)
640 return ret;
641
642 char *path = (char *) malloc(size + 1, 0);
643 ASSERT(path);
644
645 if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
646 (path[size] == 0)) {
647 /*
648 * Prevent other functions from messing with sysinfo while we
649 * are reading it.
650 */
651 mutex_lock(&sysinfo_lock);
652 ret = sysinfo_get_item(path, NULL, dry_run);
653 mutex_unlock(&sysinfo_lock);
654 }
655
656 free(path);
657 return ret;
658}
659
660/** Return sysinfo keys determined by name
661 *
662 * Should be called with sysinfo_lock held.
663 *
664 * @param name Sysinfo path.
665 * @param root Root item of the sysinfo (sub)tree.
666 * If it is NULL then consider the global
667 * sysinfo tree.
668 * @param dry_run Do not actually get any generated
669 * binary data, just calculate the size.
670 *
671 * @return Item value (constant or generated).
672 *
673 */
674NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
675 sysinfo_item_t **root, bool dry_run)
676{
677 if (root == NULL)
678 root = &global_root;
679
680 /* Try to find the item */
681 sysinfo_item_t *item = sysinfo_find_item(name, *root, NULL,
682 dry_run);
683
684 sysinfo_return_t ret;
685
686 if ((item != NULL) && (item->subtree_type == SYSINFO_SUBTREE_TABLE)) {
687 /*
688 * Subtree found in the fixed sysinfo tree.
689 * Calculate the size of subkeys.
690 */
691 size_t size = 0;
692 for (sysinfo_item_t *cur = item->subtree.table; cur;
693 cur = cur->next)
694 size += str_size(cur->name) + 1;
695
696 if (dry_run) {
697 ret.tag = SYSINFO_VAL_FUNCTION_DATA;
698 ret.data.data = NULL;
699 ret.data.size = size;
700 } else {
701 /* Allocate buffer for subkeys */
702 char *names = (char *) malloc(size, FRAME_ATOMIC);
703 if (names == NULL)
704 return ret;
705
706 size_t pos = 0;
707 for (sysinfo_item_t *cur = item->subtree.table; cur;
708 cur = cur->next) {
709 str_cpy(names + pos, size - pos, cur->name);
710 pos += str_size(cur->name) + 1;
711 }
712
713 /* Correct return value */
714 ret.tag = SYSINFO_VAL_FUNCTION_DATA;
715 ret.data.data = (void *) names;
716 ret.data.size = size;
717 }
718 } else {
719 /* No item in the fixed sysinfo tree */
720 ret.tag = SYSINFO_VAL_UNDEFINED;
721 }
722
723 return ret;
724}
725
726/** Return sysinfo keys determined by name from user space
727 *
728 * The path string passed from the user space has to be properly
729 * null-terminated (the last passed character must be null).
730 *
731 * @param ptr Sysinfo path in the user address space.
732 * @param size Size of the path string.
733 * @param dry_run Do not actually get any generated
734 * binary data, just calculate the size.
735 *
736 */
737NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
738 bool dry_run)
739{
740 sysinfo_return_t ret;
741 ret.tag = SYSINFO_VAL_UNDEFINED;
742
743 if (size > SYSINFO_MAX_PATH)
744 return ret;
745
746 char *path = (char *) malloc(size + 1, 0);
747 ASSERT(path);
748
749 if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
750 (path[size] == 0)) {
751 /*
752 * Prevent other functions from messing with sysinfo while we
753 * are reading it.
754 */
755 mutex_lock(&sysinfo_lock);
756 ret = sysinfo_get_keys(path, NULL, dry_run);
757 mutex_unlock(&sysinfo_lock);
758 }
759
760 free(path);
761 return ret;
762}
763
764/** Get the sysinfo keys size (syscall)
765 *
766 * The path string passed from the user space has
767 * to be properly null-terminated (the last passed
768 * character must be null).
769 *
770 * @param path_ptr Sysinfo path in the user address space.
771 * @param path_size Size of the path string.
772 * @param size_ptr User space pointer where to store the
773 * keys size.
774 *
775 * @return Error code (EOK in case of no error).
776 *
777 */
778sysarg_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
779 void *size_ptr)
780{
781 int rc;
782
783 /*
784 * Get the keys.
785 *
786 * N.B.: There is no need to free any potential keys
787 * since we request a dry run.
788 */
789 sysinfo_return_t ret =
790 sysinfo_get_keys_uspace(path_ptr, path_size, true);
791
792 /* Check return data tag */
793 if (ret.tag == SYSINFO_VAL_DATA)
794 rc = copy_to_uspace(size_ptr, &ret.data.size,
795 sizeof(ret.data.size));
796 else
797 rc = EINVAL;
798
799 return (sysarg_t) rc;
800}
801
802/** Get the sysinfo keys (syscall)
803 *
804 * The path string passed from the user space has
805 * to be properly null-terminated (the last passed
806 * character must be null).
807 *
808 * If the user space buffer size does not equal
809 * the actual size of the returned data, the data
810 * is truncated.
811 *
812 * The actual size of data returned is stored to
813 * size_ptr.
814 *
815 * @param path_ptr Sysinfo path in the user address space.
816 * @param path_size Size of the path string.
817 * @param buffer_ptr User space pointer to the buffer where
818 * to store the binary data.
819 * @param buffer_size User space buffer size.
820 * @param size_ptr User space pointer where to store the
821 * binary data size.
822 *
823 * @return Error code (EOK in case of no error).
824 *
825 */
826sysarg_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
827 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
828{
829 int rc;
830
831 /* Get the keys */
832 sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
833 false);
834
835 /* Check return data tag */
836 if (ret.tag == SYSINFO_VAL_DATA) {
837 size_t size = min(ret.data.size, buffer_size);
838 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
839 if (rc == EOK)
840 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
841
842 free(ret.data.data);
843 } else
844 rc = EINVAL;
845
846 return (sysarg_t) rc;
847}
848
849/** Get the sysinfo value type (syscall)
850 *
851 * The path string passed from the user space has
852 * to be properly null-terminated (the last passed
853 * character must be null).
854 *
855 * @param path_ptr Sysinfo path in the user address space.
856 * @param path_size Size of the path string.
857 *
858 * @return Item value type.
859 *
860 */
861sysarg_t sys_sysinfo_get_val_type(void *path_ptr, size_t path_size)
862{
863 /*
864 * Get the item.
865 *
866 * N.B.: There is no need to free any potential generated
867 * binary data since we request a dry run.
868 */
869 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
870
871 /*
872 * Map generated value types to constant types (user space does
873 * not care whether the value is constant or generated).
874 */
875 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
876 ret.tag = SYSINFO_VAL_VAL;
877 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
878 ret.tag = SYSINFO_VAL_DATA;
879
880 return (sysarg_t) ret.tag;
881}
882
883/** Get the sysinfo numerical value (syscall)
884 *
885 * The path string passed from the user space has
886 * to be properly null-terminated (the last passed
887 * character must be null).
888 *
889 * @param path_ptr Sysinfo path in the user address space.
890 * @param path_size Size of the path string.
891 * @param value_ptr User space pointer where to store the
892 * numberical value.
893 *
894 * @return Error code (EOK in case of no error).
895 *
896 */
897sysarg_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
898 void *value_ptr)
899{
900 int rc;
901
902 /*
903 * Get the item.
904 *
905 * N.B.: There is no need to free any potential generated binary
906 * data since we request a dry run.
907 */
908 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
909
910 /* Only constant or generated numerical value is returned */
911 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
912 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
913 else
914 rc = EINVAL;
915
916 return (sysarg_t) rc;
917}
918
919/** Get the sysinfo binary data size (syscall)
920 *
921 * The path string passed from the user space has
922 * to be properly null-terminated (the last passed
923 * character must be null).
924 *
925 * @param path_ptr Sysinfo path in the user address space.
926 * @param path_size Size of the path string.
927 * @param size_ptr User space pointer where to store the
928 * binary data size.
929 *
930 * @return Error code (EOK in case of no error).
931 *
932 */
933sysarg_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
934 void *size_ptr)
935{
936 int rc;
937
938 /*
939 * Get the item.
940 *
941 * N.B.: There is no need to free any potential generated binary
942 * data since we request a dry run.
943 */
944 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
945
946 /* Only the size of constant or generated binary data is considered */
947 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
948 rc = copy_to_uspace(size_ptr, &ret.data.size,
949 sizeof(ret.data.size));
950 else
951 rc = EINVAL;
952
953 return (sysarg_t) rc;
954}
955
956/** Get the sysinfo binary data (syscall)
957 *
958 * The path string passed from the user space has
959 * to be properly null-terminated (the last passed
960 * character must be null).
961 *
962 * If the user space buffer size does not equal
963 * the actual size of the returned data, the data
964 * is truncated. Whether this is actually a fatal
965 * error or the data can be still interpreted as valid
966 * depends on the nature of the data and has to be
967 * decided by the user space.
968 *
969 * The actual size of data returned is stored to
970 * size_ptr.
971 *
972 * @param path_ptr Sysinfo path in the user address space.
973 * @param path_size Size of the path string.
974 * @param buffer_ptr User space pointer to the buffer where
975 * to store the binary data.
976 * @param buffer_size User space buffer size.
977 * @param size_ptr User space pointer where to store the
978 * binary data size.
979 *
980 * @return Error code (EOK in case of no error).
981 *
982 */
983sysarg_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
984 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
985{
986 int rc;
987
988 /* Get the item */
989 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size,
990 false);
991
992 /* Only constant or generated binary data is considered */
993 if ((ret.tag == SYSINFO_VAL_DATA) ||
994 (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
995 size_t size = min(ret.data.size, buffer_size);
996 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
997 if (rc == EOK)
998 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
999 } else
1000 rc = EINVAL;
1001
1002 /* N.B.: The generated binary data should be freed */
1003 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
1004 free(ret.data.data);
1005
1006 return (sysarg_t) rc;
1007}
1008
1009/** @}
1010 */
Note: See TracBrowser for help on using the repository browser.