Ignore:
File:
1 edited

Legend:

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

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