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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

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