source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ 6e121b8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6e121b8 was 6b6626d3, checked in by Jakub Jermar <jakub@…>, 15 years ago

Replace sysinfo_lock spinlock with a mutex.

  • 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
43/** Maximal sysinfo path length */
44#define SYSINFO_MAX_PATH 2048
45
46bool fb_exported = false;
47
48/** Global sysinfo tree root item */
49static sysinfo_item_t *global_root = NULL;
50
51/** Sysinfo SLAB cache */
52static slab_cache_t *sysinfo_item_slab;
53
54/** Sysinfo lock */
55static mutex_t sysinfo_lock;
56
57/** Sysinfo item constructor
58 *
59 */
60static int sysinfo_item_constructor(void *obj, int kmflag)
61{
62 sysinfo_item_t *item = (sysinfo_item_t *) obj;
63
64 item->name = NULL;
65 item->val_type = SYSINFO_VAL_UNDEFINED;
66 item->subtree_type = SYSINFO_SUBTREE_NONE;
67 item->subtree.table = NULL;
68 item->next = NULL;
69
70 return 0;
71}
72
73/** Sysinfo item destructor
74 *
75 * Note that the return value is not perfectly correct
76 * since more space might get actually freed thanks
77 * to the disposal of item->name
78 *
79 */
80static int sysinfo_item_destructor(void *obj)
81{
82 sysinfo_item_t *item = (sysinfo_item_t *) obj;
83
84 if (item->name != NULL)
85 free(item->name);
86
87 return 0;
88}
89
90/** Initialize sysinfo subsystem
91 *
92 * Create SLAB cache for sysinfo items.
93 *
94 */
95void sysinfo_init(void)
96{
97 sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
98 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
99 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
100
101 mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE);
102}
103
104/** Recursively find an item in sysinfo tree
105 *
106 * Should be called with interrupts disabled
107 * and 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 */
123static 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.get_data(name + i + 1, dry_run);
154 return NULL;
155 default:
156 /* Not found, no data generated */
157 *ret = NULL;
158 return NULL;
159 }
160 }
161
162 cur = cur->next;
163 }
164
165 /* Not found, no data generated */
166 *ret = NULL;
167 return NULL;
168}
169
170/** Recursively create items in sysinfo tree
171 *
172 * Should be called with interrupts disabled
173 * and 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 */
184static 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 unative_t val)
301{
302 /* Protect sysinfo tree consistency */
303 ipl_t ipl = interrupts_disable();
304 mutex_lock(&sysinfo_lock);
305
306 if (root == NULL)
307 root = &global_root;
308
309 sysinfo_item_t *item = sysinfo_create_path(name, root);
310 if (item != NULL) {
311 item->val_type = SYSINFO_VAL_VAL;
312 item->val.val = val;
313 }
314
315 mutex_unlock(&sysinfo_lock);
316 interrupts_restore(ipl);
317}
318
319/** Set sysinfo item with a constant binary data
320 *
321 * Note that sysinfo only stores the pointer to the
322 * binary data and does not touch it in any way. The
323 * data should be static and immortal.
324 *
325 * @param name Sysinfo path.
326 * @param root Pointer to the root item or where to store
327 * a new root item (NULL for global sysinfo root).
328 * @param data Binary data.
329 * @param size Size of the binary data.
330 *
331 */
332void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
333 void *data, size_t size)
334{
335 /* Protect sysinfo tree consistency */
336 ipl_t ipl = interrupts_disable();
337 mutex_lock(&sysinfo_lock);
338
339 if (root == NULL)
340 root = &global_root;
341
342 sysinfo_item_t *item = sysinfo_create_path(name, root);
343 if (item != NULL) {
344 item->val_type = SYSINFO_VAL_DATA;
345 item->val.data.data = data;
346 item->val.data.size = size;
347 }
348
349 mutex_unlock(&sysinfo_lock);
350 interrupts_restore(ipl);
351}
352
353/** Set sysinfo item with a generated numeric value
354 *
355 * @param name Sysinfo path.
356 * @param root Pointer to the root item or where to store
357 * a new root item (NULL for global sysinfo root).
358 * @param fn Numeric value generator function.
359 *
360 */
361void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
362 sysinfo_fn_val_t fn)
363{
364 /* Protect sysinfo tree consistency */
365 ipl_t ipl = interrupts_disable();
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 interrupts_restore(ipl);
379}
380
381/** Set sysinfo item with a generated binary data
382 *
383 * Note that each time the generator function is called
384 * it is supposed to return a new dynamically allocated
385 * data. This data is then freed by sysinfo in the context
386 * of the current sysinfo request.
387 *
388 * @param name Sysinfo path.
389 * @param root Pointer to the root item or where to store
390 * a new root item (NULL for global sysinfo root).
391 * @param fn Binary data generator function.
392 *
393 */
394void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
395 sysinfo_fn_data_t fn)
396{
397 /* Protect sysinfo tree consistency */
398 ipl_t ipl = interrupts_disable();
399 mutex_lock(&sysinfo_lock);
400
401 if (root == NULL)
402 root = &global_root;
403
404 sysinfo_item_t *item = sysinfo_create_path(name, root);
405 if (item != NULL) {
406 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
407 item->val.fn_data = fn;
408 }
409
410 mutex_unlock(&sysinfo_lock);
411 interrupts_restore(ipl);
412}
413
414/** Set sysinfo item with an undefined value
415 *
416 * @param name Sysinfo path.
417 * @param root Pointer to the root item or where to store
418 * a new root item (NULL for global sysinfo root).
419 *
420 */
421void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
422{
423 /* Protect sysinfo tree consistency */
424 ipl_t ipl = interrupts_disable();
425 mutex_lock(&sysinfo_lock);
426
427 if (root == NULL)
428 root = &global_root;
429
430 sysinfo_item_t *item = sysinfo_create_path(name, root);
431 if (item != NULL)
432 item->val_type = SYSINFO_VAL_UNDEFINED;
433
434 mutex_unlock(&sysinfo_lock);
435 interrupts_restore(ipl);
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 *
445 */
446void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
447 sysinfo_fn_subtree_t fn)
448{
449 /* Protect sysinfo tree consistency */
450 ipl_t ipl = interrupts_disable();
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.get_data = fn;
463 }
464
465 mutex_unlock(&sysinfo_lock);
466 interrupts_restore(ipl);
467}
468
469/** Sysinfo dump indentation helper routine
470 *
471 * @param depth Number of indentation characters to print.
472 *
473 */
474static void sysinfo_indent(unsigned int depth)
475{
476 unsigned int i;
477 for (i = 0; i < depth; i++)
478 printf(" ");
479}
480
481/** Dump the structure of sysinfo tree
482 *
483 * Should be called with interrupts disabled
484 * and sysinfo_lock held.
485 *
486 * @param root Root item of the current (sub)tree.
487 * @param depth Current depth in the sysinfo tree.
488 *
489 */
490static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
491{
492 sysinfo_item_t *cur = root;
493
494 /* Walk all siblings */
495 while (cur != NULL) {
496 sysinfo_indent(depth);
497
498 unative_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("+ %s\n", cur->name);
505 break;
506 case SYSINFO_VAL_VAL:
507 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
508 cur->val.val, cur->val.val);
509 break;
510 case SYSINFO_VAL_DATA:
511 printf("+ %s (%" PRIs" bytes)\n", cur->name,
512 cur->val.data.size);
513 break;
514 case SYSINFO_VAL_FUNCTION_VAL:
515 val = cur->val.fn_val(cur);
516 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
517 cur->name, val, val);
518 break;
519 case SYSINFO_VAL_FUNCTION_DATA:
520 /* N.B.: No data was actually returned (only a dry run) */
521 (void) cur->val.fn_data(cur, &size, true);
522 printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
523 size);
524 break;
525 default:
526 printf("+ %s [unknown]\n", cur->name);
527 }
528
529 /* Recursivelly nest into the subtree */
530 switch (cur->subtree_type) {
531 case SYSINFO_SUBTREE_NONE:
532 break;
533 case SYSINFO_SUBTREE_TABLE:
534 sysinfo_dump_internal(cur->subtree.table, depth + 1);
535 break;
536 case SYSINFO_SUBTREE_FUNCTION:
537 sysinfo_indent(depth + 1);
538 printf("+ [generated subtree]\n");
539 break;
540 default:
541 sysinfo_indent(depth + 1);
542 printf("+ [unknown subtree]\n");
543 }
544
545 cur = cur->next;
546 }
547}
548
549/** Dump the structure of sysinfo tree
550 *
551 * @param root Root item of the sysinfo (sub)tree.
552 * If it is NULL then consider the global
553 * sysinfo tree.
554 *
555 */
556void sysinfo_dump(sysinfo_item_t *root)
557{
558 /* Avoid other functions to mess with sysinfo
559 while we are dumping it */
560 ipl_t ipl = interrupts_disable();
561 mutex_lock(&sysinfo_lock);
562
563 if (root == NULL)
564 sysinfo_dump_internal(global_root, 0);
565 else
566 sysinfo_dump_internal(root, 0);
567
568 mutex_unlock(&sysinfo_lock);
569 interrupts_restore(ipl);
570}
571
572/** Return sysinfo item value determined by name
573 *
574 * Should be called with interrupts disabled
575 * and sysinfo_lock held.
576 *
577 * @param name Sysinfo path.
578 * @param root Root item of the sysinfo (sub)tree.
579 * If it is NULL then consider the global
580 * sysinfo tree.
581 * @param dry_run Do not actually get any generated
582 * binary data, just calculate the size.
583 *
584 * @return Item value (constant or generated).
585 *
586 */
587static sysinfo_return_t sysinfo_get_item(const char *name,
588 sysinfo_item_t **root, bool dry_run)
589{
590 if (root == NULL)
591 root = &global_root;
592
593 /* Try to find the item or generate data */
594 sysinfo_return_t ret;
595 sysinfo_return_t *ret_ptr = &ret;
596 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
597 dry_run);
598
599 if (item != NULL) {
600 /* Item found in the fixed sysinfo tree */
601
602 ret.tag = item->val_type;
603 switch (item->val_type) {
604 case SYSINFO_VAL_UNDEFINED:
605 break;
606 case SYSINFO_VAL_VAL:
607 ret.val = item->val.val;
608 break;
609 case SYSINFO_VAL_DATA:
610 ret.data = item->val.data;
611 break;
612 case SYSINFO_VAL_FUNCTION_VAL:
613 ret.val = item->val.fn_val(item);
614 break;
615 case SYSINFO_VAL_FUNCTION_DATA:
616 ret.data.data = item->val.fn_data(item, &ret.data.size,
617 dry_run);
618 break;
619 }
620 } else {
621 /* No item in the fixed sysinfo tree */
622 if (ret_ptr == NULL) {
623 /* Even no data was generated */
624 ret.tag = SYSINFO_VAL_UNDEFINED;
625 }
626 }
627
628 return ret;
629}
630
631/** Return sysinfo item determined by name from user space
632 *
633 * The path string passed from the user space has to be properly null-terminated
634 * (the last passed character must be null).
635 *
636 * @param ptr Sysinfo path in the user address space.
637 * @param size Size of the path string.
638 * @param dry_run Do not actually get any generated
639 * binary data, just calculate the size.
640 *
641 */
642static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
643 bool dry_run)
644{
645 sysinfo_return_t ret;
646 ret.tag = SYSINFO_VAL_UNDEFINED;
647
648 if (size > SYSINFO_MAX_PATH)
649 return ret;
650
651 char *path = (char *) malloc(size + 1, 0);
652 ASSERT(path);
653
654 if ((copy_from_uspace(path, ptr, size + 1) == 0)
655 && (path[size] == 0)) {
656 /*
657 * Prevent other functions from messing with sysinfo while we
658 * are reading it.
659 */
660 ipl_t ipl = interrupts_disable();
661 mutex_lock(&sysinfo_lock);
662 ret = sysinfo_get_item(path, NULL, dry_run);
663 mutex_unlock(&sysinfo_lock);
664 interrupts_restore(ipl);
665 }
666 free(path);
667 return ret;
668}
669
670/** Get the sysinfo value type (syscall)
671 *
672 * The path string passed from the user space has
673 * to be properly null-terminated (the last passed
674 * character must be null).
675 *
676 * @param path_ptr Sysinfo path in the user address space.
677 * @param path_size Size of the path string.
678 *
679 * @return Item value type.
680 *
681 */
682unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
683{
684 /*
685 * Get the item.
686 *
687 * N.B.: There is no need to free any potential generated
688 * binary data since we request a dry run.
689 */
690 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
691
692 /*
693 * Map generated value types to constant types (user space does not care
694 * whether the value is constant or generated).
695 */
696 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
697 ret.tag = SYSINFO_VAL_VAL;
698 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
699 ret.tag = SYSINFO_VAL_DATA;
700
701 return (unative_t) ret.tag;
702}
703
704/** Get the sysinfo numerical value (syscall)
705 *
706 * The path string passed from the user space has
707 * to be properly null-terminated (the last passed
708 * character must be null).
709 *
710 * @param path_ptr Sysinfo path in the user address space.
711 * @param path_size Size of the path string.
712 * @param value_ptr User space pointer where to store the
713 * numberical value.
714 *
715 * @return Error code (EOK in case of no error).
716 *
717 */
718unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
719 void *value_ptr)
720{
721 int rc;
722
723 /*
724 * Get the item.
725 *
726 * N.B.: There is no need to free any potential generated binary data
727 * since we request a dry run.
728 */
729 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
730
731 /* Only constant or generated numerical value is returned */
732 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
733 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
734 else
735 rc = EINVAL;
736
737 return (unative_t) rc;
738}
739
740/** Get the sysinfo binary data size (syscall)
741 *
742 * The path string passed from the user space has
743 * to be properly null-terminated (the last passed
744 * character must be null).
745 *
746 * @param path_ptr Sysinfo path in the user address space.
747 * @param path_size Size of the path string.
748 * @param size_ptr User space pointer where to store the
749 * binary data size.
750 *
751 * @return Error code (EOK in case of no error).
752 *
753 */
754unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
755 void *size_ptr)
756{
757 int rc;
758
759 /*
760 * Get the item.
761 *
762 * N.B.: There is no need to free any potential generated binary data
763 * since we request a dry run.
764 */
765 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
766
767 /* Only the size of constant or generated binary data is considered */
768 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
769 rc = copy_to_uspace(size_ptr, &ret.data.size,
770 sizeof(ret.data.size));
771 else
772 rc = EINVAL;
773
774 return (unative_t) rc;
775}
776
777/** Get the sysinfo binary data (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 * The user space buffer must be sized exactly according
784 * to the size of the binary data, otherwise the request
785 * fails.
786 *
787 * @param path_ptr Sysinfo path in the user address space.
788 * @param path_size Size of the path string.
789 * @param buffer_ptr User space pointer to the buffer where
790 * to store the binary data.
791 * @param buffer_size User space buffer size.
792 *
793 * @return Error code (EOK in case of no error).
794 *
795 */
796unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
797 void *buffer_ptr, size_t buffer_size)
798{
799 int rc;
800
801 /* Get the item */
802 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false);
803
804 /* Only constant or generated binary data is considered */
805 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
806 /* Check destination buffer size */
807 if (ret.data.size == buffer_size)
808 rc = copy_to_uspace(buffer_ptr, ret.data.data,
809 ret.data.size);
810 else
811 rc = ENOMEM;
812 } else
813 rc = EINVAL;
814
815 /* N.B.: The generated binary data should be freed */
816 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
817 free(ret.data.data);
818
819 return (unative_t) rc;
820}
821
822/** @}
823 */
Note: See TracBrowser for help on using the repository browser.