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

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

major code revision

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