source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ 5869ce0

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

extend sysinfo generated subtree interface

  • Property mode set to 100644
File size: 21.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 either also 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 ASSERT(ret != 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 **ret = cur->subtree.generator.fn(name + i + 1, dry_run,
154 cur->subtree.generator.data);
155 return NULL;
156 default:
157 /* Not found, no data generated */
158 *ret = NULL;
159 return NULL;
160 }
161 }
162
163 cur = cur->next;
164 }
165
166 /* Not found, no data generated */
167 *ret = NULL;
168 return NULL;
169}
170
171/** Recursively create items in sysinfo tree
172 *
173 * Should be called with sysinfo_lock held.
174 *
175 * @param name Current sysinfo path suffix.
176 * @param psubtree Pointer to an already existing (sub)tree root
177 * item or where to store a new tree root item.
178 *
179 * @return Existing or newly allocated sysinfo item or NULL
180 * if the current tree configuration does not allow to
181 * create a new item.
182 *
183 */
184NO_TRACE static sysinfo_item_t *sysinfo_create_path(const char *name,
185 sysinfo_item_t **psubtree)
186{
187 ASSERT(psubtree != NULL);
188
189 if (*psubtree == NULL) {
190 /* No parent */
191
192 size_t i = 0;
193
194 /* Find the first delimiter in name */
195 while ((name[i] != 0) && (name[i] != '.'))
196 i++;
197
198 *psubtree =
199 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
200 ASSERT(*psubtree);
201
202 /* Fill in item name up to the delimiter */
203 (*psubtree)->name = str_ndup(name, i);
204 ASSERT((*psubtree)->name);
205
206 /* Create subtree items */
207 if (name[i] == '.') {
208 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
209 return sysinfo_create_path(name + i + 1,
210 &((*psubtree)->subtree.table));
211 }
212
213 /* No subtree needs to be created */
214 return *psubtree;
215 }
216
217 sysinfo_item_t *cur = *psubtree;
218
219 /* Walk all siblings */
220 while (cur != NULL) {
221 size_t i = 0;
222
223 /* Compare name with path */
224 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
225 i++;
226
227 /* Check for perfect name and path match
228 * -> item is already present.
229 */
230 if ((name[i] == 0) && (cur->name[i] == 0))
231 return cur;
232
233 /* Partial match up to the delimiter */
234 if ((name[i] == '.') && (cur->name[i] == 0)) {
235 switch (cur->subtree_type) {
236 case SYSINFO_SUBTREE_NONE:
237 /* No subtree yet, create one */
238 cur->subtree_type = SYSINFO_SUBTREE_TABLE;
239 return sysinfo_create_path(name + i + 1,
240 &(cur->subtree.table));
241 case SYSINFO_SUBTREE_TABLE:
242 /* Subtree already created, add new sibling */
243 return sysinfo_create_path(name + i + 1,
244 &(cur->subtree.table));
245 default:
246 /* Subtree items handled by a function, this
247 * cannot be overriden by a constant item.
248 */
249 return NULL;
250 }
251 }
252
253 /* No match and no more siblings to check
254 * -> create a new sibling item.
255 */
256 if (cur->next == NULL) {
257 /* Find the first delimiter in name */
258 i = 0;
259 while ((name[i] != 0) && (name[i] != '.'))
260 i++;
261
262 sysinfo_item_t *item =
263 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
264 ASSERT(item);
265
266 cur->next = item;
267
268 /* Fill in item name up to the delimiter */
269 item->name = str_ndup(name, i);
270 ASSERT(item->name);
271
272 /* Create subtree items */
273 if (name[i] == '.') {
274 item->subtree_type = SYSINFO_SUBTREE_TABLE;
275 return sysinfo_create_path(name + i + 1,
276 &(item->subtree.table));
277 }
278
279 /* No subtree needs to be created */
280 return item;
281 }
282
283 cur = cur->next;
284 }
285
286 /* Unreachable */
287 ASSERT(false);
288 return NULL;
289}
290
291/** Set sysinfo item with a constant numeric value
292 *
293 * @param name Sysinfo path.
294 * @param root Pointer to the root item or where to store
295 * a new root item (NULL for global sysinfo root).
296 * @param val Value to store in the item.
297 *
298 */
299void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
300 sysarg_t val)
301{
302 /* Protect sysinfo tree consistency */
303 mutex_lock(&sysinfo_lock);
304
305 if (root == NULL)
306 root = &global_root;
307
308 sysinfo_item_t *item = sysinfo_create_path(name, root);
309 if (item != NULL) {
310 item->val_type = SYSINFO_VAL_VAL;
311 item->val.val = val;
312 }
313
314 mutex_unlock(&sysinfo_lock);
315}
316
317/** Set sysinfo item with a constant binary data
318 *
319 * Note that sysinfo only stores the pointer to the
320 * binary data and does not touch it in any way. The
321 * data should be static and immortal.
322 *
323 * @param name Sysinfo path.
324 * @param root Pointer to the root item or where to store
325 * a new root item (NULL for global sysinfo root).
326 * @param data Binary data.
327 * @param size Size of the binary data.
328 *
329 */
330void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
331 void *data, size_t size)
332{
333 /* Protect sysinfo tree consistency */
334 mutex_lock(&sysinfo_lock);
335
336 if (root == NULL)
337 root = &global_root;
338
339 sysinfo_item_t *item = sysinfo_create_path(name, root);
340 if (item != NULL) {
341 item->val_type = SYSINFO_VAL_DATA;
342 item->val.data.data = data;
343 item->val.data.size = size;
344 }
345
346 mutex_unlock(&sysinfo_lock);
347}
348
349/** Set sysinfo item with a generated numeric value
350 *
351 * @param name Sysinfo path.
352 * @param root Pointer to the root item or where to store
353 * a new root item (NULL for global sysinfo root).
354 * @param fn Numeric value generator function.
355 *
356 */
357void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
358 sysinfo_fn_val_t fn)
359{
360 /* Protect sysinfo tree consistency */
361 mutex_lock(&sysinfo_lock);
362
363 if (root == NULL)
364 root = &global_root;
365
366 sysinfo_item_t *item = sysinfo_create_path(name, root);
367 if (item != NULL) {
368 item->val_type = SYSINFO_VAL_FUNCTION_VAL;
369 item->val.fn_val = fn;
370 }
371
372 mutex_unlock(&sysinfo_lock);
373}
374
375/** Set sysinfo item with a generated binary data
376 *
377 * Note that each time the generator function is called
378 * it is supposed to return a new dynamically allocated
379 * data. This data is then freed by sysinfo in the context
380 * of the current sysinfo request.
381 *
382 * @param name Sysinfo path.
383 * @param root Pointer to the root item or where to store
384 * a new root item (NULL for global sysinfo root).
385 * @param fn Binary data generator function.
386 *
387 */
388void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
389 sysinfo_fn_data_t fn)
390{
391 /* Protect sysinfo tree consistency */
392 mutex_lock(&sysinfo_lock);
393
394 if (root == NULL)
395 root = &global_root;
396
397 sysinfo_item_t *item = sysinfo_create_path(name, root);
398 if (item != NULL) {
399 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
400 item->val.fn_data = fn;
401 }
402
403 mutex_unlock(&sysinfo_lock);
404}
405
406/** Set sysinfo item with an undefined value
407 *
408 * @param name Sysinfo path.
409 * @param root Pointer to the root item or where to store
410 * a new root item (NULL for global sysinfo root).
411 *
412 */
413void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
414{
415 /* Protect sysinfo tree consistency */
416 mutex_lock(&sysinfo_lock);
417
418 if (root == NULL)
419 root = &global_root;
420
421 sysinfo_item_t *item = sysinfo_create_path(name, root);
422 if (item != NULL)
423 item->val_type = SYSINFO_VAL_UNDEFINED;
424
425 mutex_unlock(&sysinfo_lock);
426}
427
428/** Set sysinfo item with a generated subtree
429 *
430 * @param name Sysinfo path.
431 * @param root Pointer to the root item or where to store
432 * a new root item (NULL for global sysinfo root).
433 * @param fn Subtree generator function.
434 * @param data Private data to be passed to the generator.
435 *
436 */
437void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
438 sysinfo_fn_subtree_t fn, void *data)
439{
440 /* Protect sysinfo tree consistency */
441 mutex_lock(&sysinfo_lock);
442
443 if (root == NULL)
444 root = &global_root;
445
446 sysinfo_item_t *item = sysinfo_create_path(name, root);
447
448 /* Change the type of the subtree only if it is not already
449 a fixed subtree */
450 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
451 item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
452 item->subtree.generator.fn = fn;
453 item->subtree.generator.data = data;
454 }
455
456 mutex_unlock(&sysinfo_lock);
457}
458
459/** Sysinfo dump indentation helper routine
460 *
461 * @param depth Number of indentation characters to print.
462 *
463 */
464NO_TRACE static void sysinfo_indent(unsigned int depth)
465{
466 unsigned int i;
467 for (i = 0; i < depth; i++)
468 printf(" ");
469}
470
471/** Dump the structure of sysinfo tree
472 *
473 * Should be called with sysinfo_lock held.
474 *
475 * @param root Root item of the current (sub)tree.
476 * @param depth Current depth in the sysinfo tree.
477 *
478 */
479NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
480{
481 sysinfo_item_t *cur = root;
482
483 /* Walk all siblings */
484 while (cur != NULL) {
485 sysinfo_indent(depth);
486
487 sysarg_t val;
488 size_t size;
489
490 /* Display node value and type */
491 switch (cur->val_type) {
492 case SYSINFO_VAL_UNDEFINED:
493 printf("+ %s\n", cur->name);
494 break;
495 case SYSINFO_VAL_VAL:
496 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
497 cur->val.val, cur->val.val);
498 break;
499 case SYSINFO_VAL_DATA:
500 printf("+ %s (%zu bytes)\n", cur->name,
501 cur->val.data.size);
502 break;
503 case SYSINFO_VAL_FUNCTION_VAL:
504 val = cur->val.fn_val(cur);
505 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
506 cur->name, val, val);
507 break;
508 case SYSINFO_VAL_FUNCTION_DATA:
509 /* N.B.: No data was actually returned (only a dry run) */
510 (void) cur->val.fn_data(cur, &size, true);
511 printf("+ %s (%zu bytes) [generated]\n", cur->name,
512 size);
513 break;
514 default:
515 printf("+ %s [unknown]\n", cur->name);
516 }
517
518 /* Recursivelly nest into the subtree */
519 switch (cur->subtree_type) {
520 case SYSINFO_SUBTREE_NONE:
521 break;
522 case SYSINFO_SUBTREE_TABLE:
523 sysinfo_dump_internal(cur->subtree.table, depth + 1);
524 break;
525 case SYSINFO_SUBTREE_FUNCTION:
526 sysinfo_indent(depth + 1);
527 printf("+ [generated subtree]\n");
528 break;
529 default:
530 sysinfo_indent(depth + 1);
531 printf("+ [unknown subtree]\n");
532 }
533
534 cur = cur->next;
535 }
536}
537
538/** Dump the structure of sysinfo tree
539 *
540 * @param root Root item of the sysinfo (sub)tree.
541 * If it is NULL then consider the global
542 * sysinfo tree.
543 *
544 */
545void sysinfo_dump(sysinfo_item_t *root)
546{
547 /* Avoid other functions to mess with sysinfo
548 while we are dumping it */
549 mutex_lock(&sysinfo_lock);
550
551 if (root == NULL)
552 sysinfo_dump_internal(global_root, 0);
553 else
554 sysinfo_dump_internal(root, 0);
555
556 mutex_unlock(&sysinfo_lock);
557}
558
559/** Return sysinfo item value determined by name
560 *
561 * Should be called with sysinfo_lock held.
562 *
563 * @param name Sysinfo path.
564 * @param root Root item of the sysinfo (sub)tree.
565 * If it is NULL then consider the global
566 * sysinfo tree.
567 * @param dry_run Do not actually get any generated
568 * binary data, just calculate the size.
569 *
570 * @return Item value (constant or generated).
571 *
572 */
573NO_TRACE static sysinfo_return_t sysinfo_get_item(const char *name,
574 sysinfo_item_t **root, bool dry_run)
575{
576 if (root == NULL)
577 root = &global_root;
578
579 /* Try to find the item or generate data */
580 sysinfo_return_t ret;
581 sysinfo_return_t *ret_ptr = &ret;
582 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
583 dry_run);
584
585 if (item != NULL) {
586 /* Item found in the fixed sysinfo tree */
587
588 ret.tag = item->val_type;
589 switch (item->val_type) {
590 case SYSINFO_VAL_UNDEFINED:
591 break;
592 case SYSINFO_VAL_VAL:
593 ret.val = item->val.val;
594 break;
595 case SYSINFO_VAL_DATA:
596 ret.data = item->val.data;
597 break;
598 case SYSINFO_VAL_FUNCTION_VAL:
599 ret.val = item->val.fn_val(item);
600 break;
601 case SYSINFO_VAL_FUNCTION_DATA:
602 ret.data.data = item->val.fn_data(item, &ret.data.size,
603 dry_run);
604 break;
605 }
606 } else {
607 /* No item in the fixed sysinfo tree */
608 if (ret_ptr == NULL) {
609 /* Even no data was generated */
610 ret.tag = SYSINFO_VAL_UNDEFINED;
611 }
612 }
613
614 return ret;
615}
616
617/** Return sysinfo item determined by name from user space
618 *
619 * The path string passed from the user space has to be properly null-terminated
620 * (the last passed character must be null).
621 *
622 * @param ptr Sysinfo path in the user address space.
623 * @param size Size of the path string.
624 * @param dry_run Do not actually get any generated
625 * binary data, just calculate the size.
626 *
627 */
628NO_TRACE static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
629 bool dry_run)
630{
631 sysinfo_return_t ret;
632 ret.tag = SYSINFO_VAL_UNDEFINED;
633
634 if (size > SYSINFO_MAX_PATH)
635 return ret;
636
637 char *path = (char *) malloc(size + 1, 0);
638 ASSERT(path);
639
640 if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
641 (path[size] == 0)) {
642 /*
643 * Prevent other functions from messing with sysinfo while we
644 * are reading it.
645 */
646 mutex_lock(&sysinfo_lock);
647 ret = sysinfo_get_item(path, NULL, dry_run);
648 mutex_unlock(&sysinfo_lock);
649 }
650
651 free(path);
652 return ret;
653}
654
655/** Get the sysinfo value type (syscall)
656 *
657 * The path string passed from the user space has
658 * to be properly null-terminated (the last passed
659 * character must be null).
660 *
661 * @param path_ptr Sysinfo path in the user address space.
662 * @param path_size Size of the path string.
663 *
664 * @return Item value type.
665 *
666 */
667sysarg_t sys_sysinfo_get_val_type(void *path_ptr, size_t path_size)
668{
669 /*
670 * Get the item.
671 *
672 * N.B.: There is no need to free any potential generated
673 * binary data since we request a dry run.
674 */
675 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
676
677 /*
678 * Map generated value types to constant types (user space does
679 * not care whether the value is constant or generated).
680 */
681 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
682 ret.tag = SYSINFO_VAL_VAL;
683 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
684 ret.tag = SYSINFO_VAL_DATA;
685
686 return (sysarg_t) ret.tag;
687}
688
689/** Get the sysinfo numerical value (syscall)
690 *
691 * The path string passed from the user space has
692 * to be properly null-terminated (the last passed
693 * character must be null).
694 *
695 * @param path_ptr Sysinfo path in the user address space.
696 * @param path_size Size of the path string.
697 * @param value_ptr User space pointer where to store the
698 * numberical value.
699 *
700 * @return Error code (EOK in case of no error).
701 *
702 */
703sysarg_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
704 void *value_ptr)
705{
706 int rc;
707
708 /*
709 * Get the item.
710 *
711 * N.B.: There is no need to free any potential generated binary
712 * data since we request a dry run.
713 */
714 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
715
716 /* Only constant or generated numerical value is returned */
717 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
718 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
719 else
720 rc = EINVAL;
721
722 return (sysarg_t) rc;
723}
724
725/** Get the sysinfo binary data size (syscall)
726 *
727 * The path string passed from the user space has
728 * to be properly null-terminated (the last passed
729 * character must be null).
730 *
731 * @param path_ptr Sysinfo path in the user address space.
732 * @param path_size Size of the path string.
733 * @param size_ptr User space pointer where to store the
734 * binary data size.
735 *
736 * @return Error code (EOK in case of no error).
737 *
738 */
739sysarg_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
740 void *size_ptr)
741{
742 int rc;
743
744 /*
745 * Get the item.
746 *
747 * N.B.: There is no need to free any potential generated binary
748 * data since we request a dry run.
749 */
750 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
751
752 /* Only the size of constant or generated binary data is considered */
753 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
754 rc = copy_to_uspace(size_ptr, &ret.data.size,
755 sizeof(ret.data.size));
756 else
757 rc = EINVAL;
758
759 return (sysarg_t) rc;
760}
761
762/** Get the sysinfo binary data (syscall)
763 *
764 * The path string passed from the user space has
765 * to be properly null-terminated (the last passed
766 * character must be null).
767 *
768 * If the user space buffer size does not equal
769 * the actual size of the returned data, the data
770 * is truncated. Whether this is actually a fatal
771 * error or the data can be still interpreted as valid
772 * depends on the nature of the data and has to be
773 * decided by the user space.
774 *
775 * The actual size of data returned is stored to
776 * size_ptr.
777 *
778 * @param path_ptr Sysinfo path in the user address space.
779 * @param path_size Size of the path string.
780 * @param buffer_ptr User space pointer to the buffer where
781 * to store the binary data.
782 * @param buffer_size User space buffer size.
783 * @param size_ptr User space pointer where to store the
784 * binary data size.
785 *
786 * @return Error code (EOK in case of no error).
787 *
788 */
789sysarg_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
790 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
791{
792 int rc;
793
794 /* Get the item */
795 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size,
796 false);
797
798 /* Only constant or generated binary data is considered */
799 if ((ret.tag == SYSINFO_VAL_DATA) ||
800 (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
801 size_t size = min(ret.data.size, buffer_size);
802 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
803 if (rc == EOK)
804 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
805 } else
806 rc = EINVAL;
807
808 /* N.B.: The generated binary data should be freed */
809 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
810 free(ret.data.data);
811
812 return (sysarg_t) rc;
813}
814
815/** @}
816 */
Note: See TracBrowser for help on using the repository browser.