Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/sysinfo/sysinfo.c

    ra71c158 r7e752b2  
    3737#include <print.h>
    3838#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
    3945
    4046bool fb_exported = false;
    41 sysinfo_item_t *_root = NULL;
    42 
    43 static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree)
    44 {
    45         if (subtree == NULL)
    46                 return NULL;
    47        
    48         while (subtree != NULL) {
    49                 int i = 0;
    50                 char *a = (char *) name;
    51                 char *b = subtree->name;
    52                
    53                 while ((a[i] == b[i]) && (b[i]))
     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 */
     60NO_TRACE static 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 */
     80NO_TRACE static 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 */
     122NO_TRACE static 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]))
    54136                        i++;
    55137               
    56                 if ((!a[i]) && (!b[i]))  /* Last name in path matches */
    57                         return subtree;
    58                
    59                 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
    60                         if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
    61                                 return sysinfo_find_item(a + i + 1, subtree->subinfo.table);
     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 */
     182NO_TRACE static 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++;
    62259                       
    63                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    64                         //      return NULL;
     260                        sysinfo_item_t *item =
     261                            (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     262                        ASSERT(item);
    65263                       
    66                         return NULL; /* No subinfo */
    67                 }
    68                 /* No matches try next */
    69                 subtree = subtree->next;
    70                 i = 0;
    71         }
    72         return NULL;
    73 }
    74 
    75 static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree)
    76 {
    77         sysinfo_item_t *subtree;
    78         subtree = *psubtree;
    79        
    80         if (subtree == NULL) {
    81                 sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
    82                 int i = 0, j;
     264                        cur->next = item;
    83265                       
    84                 ASSERT(item);
    85                 *psubtree = item;
    86                 item->next = NULL;
    87                 item->val_type = SYSINFO_VAL_UNDEFINED;
    88                 item->subinfo.table = NULL;
    89 
    90                 while (name[i] && (name[i] != '.'))
    91                         i++;
     266                        /* Fill in item name up to the delimiter */
     267                        item->name = str_ndup(name, i);
     268                        ASSERT(item->name);
    92269                       
    93                 item->name = malloc(i, 0);
    94                 ASSERT(item->name);
    95 
    96                 for (j = 0; j < i; j++)
    97                         item->name[j] = name[j];
    98                 item->name[j] = 0;
    99                        
    100                 if (name[i]) { /* =='.' */
    101                         item->subinfo_type = SYSINFO_SUBINFO_TABLE;
    102                         return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
    103                 }
    104                 item->subinfo_type = SYSINFO_SUBINFO_NONE;
    105                 return item;
    106         }
    107 
    108         while (subtree != NULL) {
    109                 int i = 0, j;
    110                 char *a = (char *) name;
    111                 char *b = subtree->name;
    112                
    113                 while ((a[i] == b[i]) && (b[i]))
    114                         i++;
    115                
    116                 if ((!a[i]) && (!b[i])) /* Last name in path matches */
    117                         return subtree;
    118                
    119                 if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
    120                         if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
    121                                 return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table));
    122                        
    123                         if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) {
    124                                 subtree->subinfo_type = SYSINFO_SUBINFO_TABLE;
    125                                 return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table));
     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));
    126275                        }
    127276                       
    128                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    129                         //      return NULL;
    130                        
    131                         return NULL;
     277                        /* No subtree needs to be created */
     278                        return item;
    132279                }
    133                 /* No matches try next or create new*/
    134                 if (subtree->next == NULL) {
    135                         sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
    136                        
    137                         ASSERT(item);
    138                         subtree->next = item;
    139                         item->next = NULL;
    140                         item->val_type = SYSINFO_VAL_UNDEFINED;
    141                         item->subinfo.table = NULL;
    142 
    143                         i = 0;
    144                         while (name[i] && (name[i] != '.'))
    145                                 i++;
    146 
    147                         item->name = malloc(i, 0);
    148                         ASSERT(item->name);
    149                        
    150                         for (j = 0; j < i; j++)
    151                                 item->name[j] = name[j];
    152                        
    153                         item->name[j] = 0;
    154 
    155                         if(name[i]) { /* =='.' */
    156                                 item->subinfo_type = SYSINFO_SUBINFO_TABLE;
    157                                 return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
    158                         }
    159                         item->subinfo_type = SYSINFO_SUBINFO_NONE;
    160                         return item;
    161                 } else {
    162                         subtree = subtree->next;
    163                         i = 0;
    164                 }       
    165         }
    166 
    167         panic("Not reached.");
     280               
     281                cur = cur->next;
     282        }
     283       
     284        /* Unreachable */
     285        ASSERT(false);
    168286        return NULL;
    169287}
    170288
    171 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
    172 {
     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       
    173303        if (root == NULL)
    174                 root = &_root;
    175        
    176         /* If already created create only returns pointer
    177            If not, create it */
     304                root = &global_root;
     305       
    178306        sysinfo_item_t *item = sysinfo_create_path(name, root);
    179        
    180         if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
    181                 item->val.val = val;                   
     307        if (item != NULL) {
    182308                item->val_type = SYSINFO_VAL_VAL;
    183         }
    184 }
    185 
    186 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
    187 {
     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       
    188334        if (root == NULL)
    189                 root = &_root;
    190        
    191         /* If already created create only returns pointer
    192            If not, create it */
     335                root = &global_root;
     336       
    193337        sysinfo_item_t *item = sysinfo_create_path(name, root);
    194        
    195         if (item != NULL) { /* If in subsystem, unable to create or return so  unable to set */
    196                 item->val.fn = fn;                   
    197                 item->val_type = SYSINFO_VAL_FUNCTION;
    198         }
    199 }
    200 
    201 
     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 */
    202411void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    203412{
     413        /* Protect sysinfo tree consistency */
     414        mutex_lock(&sysinfo_lock);
     415       
    204416        if (root == NULL)
    205                 root = &_root;
    206        
    207         /* If already created create only returns pointer
    208            If not, create it */
     417                root = &global_root;
     418       
    209419        sysinfo_item_t *item = sysinfo_create_path(name, root);
    210        
    211420        if (item != NULL)
    212421                item->val_type = SYSINFO_VAL_UNDEFINED;
    213 }
    214 
    215 
    216 void sysinfo_dump(sysinfo_item_t **proot, int depth)
    217 {
    218         sysinfo_item_t *root;
    219         if (proot == NULL)
    220                 proot = &_root;
    221        
    222         root = *proot;
    223        
    224         while (root != NULL) {
    225                 int i;
    226                 unative_t val = 0;
    227                 char *vtype = NULL;
    228                
    229                
    230                 for (i = 0; i < depth; i++)
    231                         printf("  ");
    232                
    233                 switch (root->val_type) {
     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 */
     460NO_TRACE static 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 */
     475NO_TRACE static 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) {
    234488                case SYSINFO_VAL_UNDEFINED:
    235                         val = 0;
    236                         vtype = "UND";
     489                        printf("+ %s\n", cur->name);
    237490                        break;
    238491                case SYSINFO_VAL_VAL:
    239                         val = root->val.val;
    240                         vtype = "VAL";
    241                         break;
    242                 case SYSINFO_VAL_FUNCTION:
    243                         val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
    244                         vtype = "FUN";
    245                         break;
     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 (%zu 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 (%zu bytes) [generated]\n", cur->name,
     508                            size);
     509                        break;
     510                default:
     511                        printf("+ %s [unknown]\n", cur->name);
    246512                }
    247513               
    248                 printf("%s    %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val,
    249                         val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
    250                         "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
    251                         "TAB" : "FUN"));
    252                
    253                 if (root->subinfo_type == SYSINFO_SUBINFO_TABLE)
    254                         sysinfo_dump(&(root -> subinfo.table), depth + 1);
    255                
    256                 root = root->next;
    257         }
    258 }
    259 
    260 sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root)
    261 {
    262         // TODO: Implement Subsystem subinfo (by function implemented subinfo)
    263 
    264         sysinfo_rettype_t ret = {0, false};
    265 
     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       
    266547        if (root == NULL)
    267                 root = &_root;
    268        
    269         sysinfo_item_t *item = sysinfo_find_item(name, *root);
     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 */
     569NO_TRACE static 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);
    270580       
    271581        if (item != NULL) {
    272                 if (item->val_type == SYSINFO_VAL_UNDEFINED)
    273                         return ret;
     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 */
     624NO_TRACE static 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);
    274790                else
    275                         ret.valid = true;
    276                
    277                 if (item->val_type == SYSINFO_VAL_VAL)
    278                         ret.val = item->val.val;
    279                 else
    280                         ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
    281         }
    282         return ret;
    283 }
    284 
    285 #define SYSINFO_MAX_LEN 1024
    286 
    287 unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
    288 {
    289         char *str;
    290         sysinfo_rettype_t ret = {0, 0};
    291 
    292         if (len > SYSINFO_MAX_LEN)
    293                 return ret.valid;
    294         str = malloc(len + 1, 0);
    295        
    296         ASSERT(str);
    297         if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
    298                 ret = sysinfo_get_val(str, NULL);
    299        
    300         free(str);
    301         return ret.valid;
    302 }
    303 
    304 unative_t sys_sysinfo_value(unative_t ptr, unative_t len)
    305 {
    306         char *str;
    307         sysinfo_rettype_t ret = {0, 0};
    308        
    309         if (len > SYSINFO_MAX_LEN)
    310                 return ret.val;
    311         str = malloc(len + 1, 0);
    312        
    313         ASSERT(str);
    314         if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
    315                 ret = sysinfo_get_val(str, NULL);
    316        
    317         free(str);
    318         return ret.val;
     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;
    319800}
    320801
Note: See TracChangeset for help on using the changeset viewer.