source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ 9f0318c

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

avoid the possibility for infinite looping on fetching sysinfo values
still make the tests in statistical functions more robust
this fixes ticket #237

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