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

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

Do not hold the sysinfo spinlock either when doing copy_from_uspace().

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