Ignore:
File:
1 edited

Legend:

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

    rc6218327 ra71c158  
    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
    4539
    4640bool fb_exported = false;
    47 
    48 /** Global sysinfo tree root item */
    49 static sysinfo_item_t *global_root = NULL;
    50 
    51 /** Sysinfo SLAB cache */
    52 static slab_cache_t *sysinfo_item_slab;
    53 
    54 /** Sysinfo lock */
    55 static mutex_t sysinfo_lock;
    56 
    57 /** Sysinfo item constructor
    58  *
    59  */
    60 static 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;
    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  */
    80 static 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 
    90 /** Initialize sysinfo subsystem
    91  *
    92  * Create SLAB cache for sysinfo items.
    93  *
    94  */
    95 void 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  */
    122 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]))
     41sysinfo_item_t *_root = NULL;
     42
     43static 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]))
    13654                        i++;
    13755               
    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;
     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);
     62                       
     63                        //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
     64                        //      return NULL;
     65                       
     66                        return NULL; /* No subinfo */
     67                }
     68                /* No matches try next */
     69                subtree = subtree->next;
     70                i = 0;
     71        }
     72        return NULL;
     73}
     74
     75static 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;
     83                       
     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++;
     92                       
     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));
    158126                        }
     127                       
     128                        //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
     129                        //      return NULL;
     130                       
     131                        return NULL;
    159132                }
    160                
    161                 cur = cur->next;
    162         }
    163        
    164         /* Not found, no data generated */
    165         *ret = NULL;
     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.");
    166168        return NULL;
    167169}
    168170
    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  */
    182 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++;
    259                        
    260                         sysinfo_item_t *item =
    261                             (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
    262                         ASSERT(item);
    263                        
    264                         cur->next = item;
    265                        
    266                         /* Fill in item name up to the delimiter */
    267                         item->name = str_ndup(name, i);
    268                         ASSERT(item->name);
    269                        
    270                         /* Create subtree items */
    271                         if (name[i] == '.') {
    272                                 item->subtree_type = SYSINFO_SUBTREE_TABLE;
    273                                 return sysinfo_create_path(name + i + 1,
    274                                     &(item->subtree.table));
    275                         }
    276                        
    277                         /* No subtree needs to be created */
    278                         return item;
    279                 }
    280                
    281                 cur = cur->next;
    282         }
    283        
    284         /* Unreachable */
    285         ASSERT(false);
    286         return NULL;
    287 }
    288 
    289 /** Set sysinfo item with a constant numeric value
    290  *
    291  * @param name Sysinfo path.
    292  * @param root Pointer to the root item or where to store
    293  *             a new root item (NULL for global sysinfo root).
    294  * @param val  Value to store in the item.
    295  *
    296  */
    297 void 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        
     171void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
     172{
    303173        if (root == NULL)
    304                 root = &global_root;
    305        
     174                root = &_root;
     175       
     176        /* If already created create only returns pointer
     177           If not, create it */
    306178        sysinfo_item_t *item = sysinfo_create_path(name, root);
    307         if (item != NULL) {
     179       
     180        if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
     181                item->val.val = val;                   
    308182                item->val_type = SYSINFO_VAL_VAL;
    309                 item->val.val = val;
    310         }
    311        
    312         mutex_unlock(&sysinfo_lock);
    313 }
    314 
    315 /** Set sysinfo item with a constant binary data
    316  *
    317  * Note that sysinfo only stores the pointer to the
    318  * binary data and does not touch it in any way. The
    319  * data should be static and immortal.
    320  *
    321  * @param name Sysinfo path.
    322  * @param root Pointer to the root item or where to store
    323  *             a new root item (NULL for global sysinfo root).
    324  * @param data Binary data.
    325  * @param size Size of the binary data.
    326  *
    327  */
    328 void 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        
     183        }
     184}
     185
     186void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
     187{
    334188        if (root == NULL)
    335                 root = &global_root;
    336        
     189                root = &_root;
     190       
     191        /* If already created create only returns pointer
     192           If not, create it */
    337193        sysinfo_item_t *item = sysinfo_create_path(name, root);
    338         if (item != NULL) {
    339                 item->val_type = SYSINFO_VAL_DATA;
    340                 item->val.data.data = data;
    341                 item->val.data.size = size;
    342         }
    343        
    344         mutex_unlock(&sysinfo_lock);
    345 }
    346 
    347 /** Set sysinfo item with a generated numeric value
    348  *
    349  * @param name Sysinfo path.
    350  * @param root Pointer to the root item or where to store
    351  *             a new root item (NULL for global sysinfo root).
    352  * @param fn   Numeric value generator function.
    353  *
    354  */
    355 void 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        
     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
     202void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
     203{
    361204        if (root == NULL)
    362                 root = &global_root;
    363        
     205                root = &_root;
     206       
     207        /* If already created create only returns pointer
     208           If not, create it */
    364209        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  */
    386 void 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  */
    411 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    412 {
    413         /* Protect sysinfo tree consistency */
    414         mutex_lock(&sysinfo_lock);
    415        
    416         if (root == NULL)
    417                 root = &global_root;
    418        
    419         sysinfo_item_t *item = sysinfo_create_path(name, root);
     210       
    420211        if (item != NULL)
    421212                item->val_type = SYSINFO_VAL_UNDEFINED;
    422        
    423         mutex_unlock(&sysinfo_lock);
    424 }
    425 
    426 /** Set sysinfo item with a generated subtree
    427  *
    428  * @param name Sysinfo path.
    429  * @param root Pointer to the root item or where to store
    430  *             a new root item (NULL for global sysinfo root).
    431  * @param fn   Subtree generator function.
    432  *
    433  */
    434 void 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  */
    460 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  */
    475 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) {
     213}
     214
     215
     216void 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) {
    488234                case SYSINFO_VAL_UNDEFINED:
    489                         printf("+ %s\n", cur->name);
     235                        val = 0;
     236                        vtype = "UND";
    490237                        break;
    491238                case SYSINFO_VAL_VAL:
    492                         printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
    493                             cur->val.val, cur->val.val);
     239                        val = root->val.val;
     240                        vtype = "VAL";
    494241                        break;
    495                 case SYSINFO_VAL_DATA:
    496                         printf("+ %s (%" PRIs" bytes)\n", cur->name,
    497                             cur->val.data.size);
    498                         break;
    499                 case SYSINFO_VAL_FUNCTION_VAL:
    500                         val = cur->val.fn_val(cur);
    501                         printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
    502                             cur->name, val, val);
    503                         break;
    504                 case SYSINFO_VAL_FUNCTION_DATA:
    505                         /* N.B.: No data was actually returned (only a dry run) */
    506                         (void) cur->val.fn_data(cur, &size, true);
    507                         printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
    508                             size);
    509                         break;
    510                 default:
    511                         printf("+ %s [unknown]\n", cur->name);
    512                 }
    513                
    514                 /* Recursivelly nest into the subtree */
    515                 switch (cur->subtree_type) {
    516                 case SYSINFO_SUBTREE_NONE:
    517                         break;
    518                 case SYSINFO_SUBTREE_TABLE:
    519                         sysinfo_dump_internal(cur->subtree.table, depth + 1);
    520                         break;
    521                 case SYSINFO_SUBTREE_FUNCTION:
    522                         sysinfo_indent(depth + 1);
    523                         printf("+ [generated subtree]\n");
    524                         break;
    525                 default:
    526                         sysinfo_indent(depth + 1);
    527                         printf("+ [unknown subtree]\n");
    528                 }
    529                
    530                 cur = cur->next;
    531         }
    532 }
    533 
    534 /** Dump the structure of sysinfo tree
    535  *
    536  * @param root  Root item of the sysinfo (sub)tree.
    537  *              If it is NULL then consider the global
    538  *              sysinfo tree.
    539  *
    540  */
    541 void sysinfo_dump(sysinfo_item_t *root)
    542 {
    543         /* Avoid other functions to mess with sysinfo
    544            while we are dumping it */
    545         mutex_lock(&sysinfo_lock);
    546        
    547         if (root == NULL)
    548                 sysinfo_dump_internal(global_root, 0);
    549         else
    550                 sysinfo_dump_internal(root, 0);
    551        
    552         mutex_unlock(&sysinfo_lock);
    553 }
    554 
    555 /** Return sysinfo item value determined by name
    556  *
    557  * Should be called with sysinfo_lock held.
    558  *
    559  * @param name    Sysinfo path.
    560  * @param root    Root item of the sysinfo (sub)tree.
    561  *                If it is NULL then consider the global
    562  *                sysinfo tree.
    563  * @param dry_run Do not actually get any generated
    564  *                binary data, just calculate the size.
    565  *
    566  * @return Item value (constant or generated).
    567  *
    568  */
    569 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);
    580        
    581         if (item != NULL) {
    582                 /* Item found in the fixed sysinfo tree */
    583                
    584                 ret.tag = item->val_type;
    585                 switch (item->val_type) {
    586                 case SYSINFO_VAL_UNDEFINED:
    587                         break;
    588                 case SYSINFO_VAL_VAL:
    589                         ret.val = item->val.val;
    590                         break;
    591                 case SYSINFO_VAL_DATA:
    592                         ret.data = item->val.data;
    593                         break;
    594                 case SYSINFO_VAL_FUNCTION_VAL:
    595                         ret.val = item->val.fn_val(item);
    596                         break;
    597                 case SYSINFO_VAL_FUNCTION_DATA:
    598                         ret.data.data = item->val.fn_data(item, &ret.data.size,
    599                             dry_run);
     242                case SYSINFO_VAL_FUNCTION:
     243                        val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
     244                        vtype = "FUN";
    600245                        break;
    601246                }
    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        
     247               
     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
     260sysinfo_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
     266        if (root == NULL)
     267                root = &_root;
     268       
     269        sysinfo_item_t *item = sysinfo_find_item(name, *root);
     270       
     271        if (item != NULL) {
     272                if (item->val_type == SYSINFO_VAL_UNDEFINED)
     273                        return ret;
     274                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        }
    610282        return ret;
    611283}
    612284
    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  */
    624 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  */
    662 unative_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  */
    698 unative_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  */
    734 unative_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  */
    776 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
    777     void *buffer_ptr, size_t buffer_size)
    778 {
    779         int rc;
    780        
    781         /* Get the item */
    782         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false);
    783 
    784         /* Only constant or generated binary data is considered */
    785         if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
    786                 /* Check destination buffer size */
    787                 if (ret.data.size == buffer_size)
    788                         rc = copy_to_uspace(buffer_ptr, ret.data.data,
    789                             ret.data.size);
    790                 else
    791                         rc = ENOMEM;
    792         } else
    793                 rc = EINVAL;
    794        
    795         /* N.B.: The generated binary data should be freed */
    796         if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
    797                 free(ret.data.data);
    798        
    799         return (unative_t) rc;
     285#define SYSINFO_MAX_LEN 1024
     286
     287unative_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
     304unative_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;
    800319}
    801320
Note: See TracChangeset for help on using the changeset viewer.