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

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

unify slab cache naming scheme (according to the type name)

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