Ignore:
File:
1 edited

Legend:

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

    re1b6742 r137691a  
    3737#include <print.h>
    3838#include <syscall/copy.h>
    39 #include <synch/spinlock.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 spinlock */
    55 SPINLOCK_STATIC_INITIALIZE_NAME(sysinfo_lock, "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 
    102 /** Recursively find an item in sysinfo tree
    103  *
    104  * Should be called with interrupts disabled
    105  * and sysinfo_lock held.
    106  *
    107  * @param name    Current sysinfo path suffix.
    108  * @param subtree Current sysinfo (sub)tree root item.
    109  * @param ret     If the return value is NULL, this argument
    110  *                can be either also NULL (i.e. no item was
    111  *                found and no data was generated) or the
    112  *                original pointer is used to store the value
    113  *                generated by a generated subtree function.
    114  * @param dry_run Do not actually get any generated
    115  *                binary data, just calculate the size.
    116  *
    117  * @return Found item or NULL if no item in the fixed tree
    118  *         was found (N.B. ret).
    119  *
    120  */
    121 static sysinfo_item_t *sysinfo_find_item(const char *name,
    122     sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run)
    123 {
    124         ASSERT(subtree != NULL);
    125         ASSERT(ret != NULL);
    126        
    127         sysinfo_item_t *cur = subtree;
    128        
    129         /* Walk all siblings */
    130         while (cur != NULL) {
    131                 size_t i = 0;
    132                
    133                 /* Compare name with path */
    134                 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]))
    13554                        i++;
    13655               
    137                 /* Check for perfect name and path match */
    138                 if ((name[i] == 0) && (cur->name[i] == 0))
    139                         return cur;
    140                
    141                 /* Partial match up to the delimiter */
    142                 if ((name[i] == '.') && (cur->name[i] == 0)) {
    143                         /* Look into the subtree */
    144                         switch (cur->subtree_type) {
    145                         case SYSINFO_SUBTREE_TABLE:
    146                                 /* Recursively find in subtree */
    147                                 return sysinfo_find_item(name + i + 1,
    148                                     cur->subtree.table, ret, dry_run);
    149                         case SYSINFO_SUBTREE_FUNCTION:
    150                                 /* Get generated data */
    151                                 **ret = cur->subtree.get_data(name + i + 1, dry_run);
    152                                 return NULL;
    153                         default:
    154                                 /* Not found, no data generated */
    155                                 *ret = NULL;
    156                                 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        }
     71        return NULL;
     72}
     73
     74static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree)
     75{
     76        sysinfo_item_t *subtree;
     77        subtree = *psubtree;
     78       
     79        if (subtree == NULL) {
     80                sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
     81                int i = 0, j;
     82                       
     83                ASSERT(item);
     84                *psubtree = item;
     85                item->next = NULL;
     86                item->val_type = SYSINFO_VAL_UNDEFINED;
     87                item->subinfo.table = NULL;
     88
     89                while (name[i] && (name[i] != '.'))
     90                        i++;
     91                       
     92                item->name = malloc(i, 0);
     93                ASSERT(item->name);
     94
     95                for (j = 0; j < i; j++)
     96                        item->name[j] = name[j];
     97                item->name[j] = 0;
     98                       
     99                if (name[i]) { /* =='.' */
     100                        item->subinfo_type = SYSINFO_SUBINFO_TABLE;
     101                        return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
     102                }
     103                item->subinfo_type = SYSINFO_SUBINFO_NONE;
     104                return item;
     105        }
     106
     107        while (subtree != NULL) {
     108                int i = 0, j;
     109                char *a = (char *) name;
     110                char *b = subtree->name;
     111               
     112                while ((a[i] == b[i]) && (b[i]))
     113                        i++;
     114               
     115                if ((!a[i]) && (!b[i])) /* Last name in path matches */
     116                        return subtree;
     117               
     118                if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
     119                        if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
     120                                return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table));
     121                       
     122                        if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) {
     123                                subtree->subinfo_type = SYSINFO_SUBINFO_TABLE;
     124                                return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table));
    157125                        }
     126                       
     127                        //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
     128                        //      return NULL;
     129                       
     130                        return NULL;
    158131                }
    159                
    160                 cur = cur->next;
    161         }
    162        
    163         /* Not found, no data generated */
    164         *ret = NULL;
     132                /* No matches try next or create new*/
     133                if (subtree->next == NULL) {
     134                        sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
     135                       
     136                        ASSERT(item);
     137                        subtree->next = item;
     138                        item->next = NULL;
     139                        item->val_type = SYSINFO_VAL_UNDEFINED;
     140                        item->subinfo.table = NULL;
     141
     142                        i = 0;
     143                        while (name[i] && (name[i] != '.'))
     144                                i++;
     145
     146                        item->name = malloc(i, 0);
     147                        ASSERT(item->name);
     148                       
     149                        for (j = 0; j < i; j++)
     150                                item->name[j] = name[j];
     151                       
     152                        item->name[j] = 0;
     153
     154                        if(name[i]) { /* =='.' */
     155                                item->subinfo_type = SYSINFO_SUBINFO_TABLE;
     156                                return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
     157                        }
     158                        item->subinfo_type = SYSINFO_SUBINFO_NONE;
     159                        return item;
     160                } else
     161                        subtree = subtree->next;
     162        }
     163
     164        panic("Not reached.");
    165165        return NULL;
    166166}
    167167
    168 /** Recursively create items in sysinfo tree
    169  *
    170  * Should be called with interrupts disabled
    171  * and 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         ipl_t ipl = interrupts_disable();
    302         spinlock_lock(&sysinfo_lock);
    303        
     168void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
     169{
    304170        if (root == NULL)
    305                 root = &global_root;
    306        
     171                root = &_root;
     172       
     173        /* If already created create only returns pointer
     174           If not, create it */
    307175        sysinfo_item_t *item = sysinfo_create_path(name, root);
    308         if (item != NULL) {
     176       
     177        if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
     178                item->val.val = val;                   
    309179                item->val_type = SYSINFO_VAL_VAL;
    310                 item->val.val = val;
    311         }
    312        
    313         spinlock_unlock(&sysinfo_lock);
    314         interrupts_restore(ipl);
    315 }
    316 
    317 /** Set sysinfo item with a constant binary data
    318  *
    319  * Note that sysinfo only stores the pointer to the
    320  * binary data and does not touch it in any way. The
    321  * data should be static and immortal.
    322  *
    323  * @param name Sysinfo path.
    324  * @param root Pointer to the root item or where to store
    325  *             a new root item (NULL for global sysinfo root).
    326  * @param data Binary data.
    327  * @param size Size of the binary data.
    328  *
    329  */
    330 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
    331     void *data, size_t size)
    332 {
    333         /* Protect sysinfo tree consistency */
    334         ipl_t ipl = interrupts_disable();
    335         spinlock_lock(&sysinfo_lock);
    336        
     180        }
     181}
     182
     183void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
     184{
    337185        if (root == NULL)
    338                 root = &global_root;
    339        
     186                root = &_root;
     187       
     188        /* If already created create only returns pointer
     189           If not, create it */
    340190        sysinfo_item_t *item = sysinfo_create_path(name, root);
    341         if (item != NULL) {
    342                 item->val_type = SYSINFO_VAL_DATA;
    343                 item->val.data.data = data;
    344                 item->val.data.size = size;
    345         }
    346        
    347         spinlock_unlock(&sysinfo_lock);
    348         interrupts_restore(ipl);
    349 }
    350 
    351 /** Set sysinfo item with a generated numeric value
    352  *
    353  * @param name Sysinfo path.
    354  * @param root Pointer to the root item or where to store
    355  *             a new root item (NULL for global sysinfo root).
    356  * @param fn   Numeric value generator function.
    357  *
    358  */
    359 void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
    360     sysinfo_fn_val_t fn)
    361 {
    362         /* Protect sysinfo tree consistency */
    363         ipl_t ipl = interrupts_disable();
    364         spinlock_lock(&sysinfo_lock);
    365        
     191       
     192        if (item != NULL) { /* If in subsystem, unable to create or return so  unable to set */
     193                item->val.fn = fn;                   
     194                item->val_type = SYSINFO_VAL_FUNCTION;
     195        }
     196}
     197
     198
     199void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
     200{
    366201        if (root == NULL)
    367                 root = &global_root;
    368        
     202                root = &_root;
     203       
     204        /* If already created create only returns pointer
     205           If not, create it */
    369206        sysinfo_item_t *item = sysinfo_create_path(name, root);
    370         if (item != NULL) {
    371                 item->val_type = SYSINFO_VAL_FUNCTION_VAL;
    372                 item->val.fn_val = fn;
    373         }
    374        
    375         spinlock_unlock(&sysinfo_lock);
    376         interrupts_restore(ipl);
    377 }
    378 
    379 /** Set sysinfo item with a generated binary data
    380  *
    381  * Note that each time the generator function is called
    382  * it is supposed to return a new dynamically allocated
    383  * data. This data is then freed by sysinfo in the context
    384  * of the current sysinfo request.
    385  *
    386  * @param name Sysinfo path.
    387  * @param root Pointer to the root item or where to store
    388  *             a new root item (NULL for global sysinfo root).
    389  * @param fn   Binary data generator function.
    390  *
    391  */
    392 void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
    393     sysinfo_fn_data_t fn)
    394 {
    395         /* Protect sysinfo tree consistency */
    396         ipl_t ipl = interrupts_disable();
    397         spinlock_lock(&sysinfo_lock);
    398        
    399         if (root == NULL)
    400                 root = &global_root;
    401        
    402         sysinfo_item_t *item = sysinfo_create_path(name, root);
    403         if (item != NULL) {
    404                 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
    405                 item->val.fn_data = fn;
    406         }
    407        
    408         spinlock_unlock(&sysinfo_lock);
    409         interrupts_restore(ipl);
    410 }
    411 
    412 /** Set sysinfo item with an undefined value
    413  *
    414  * @param name Sysinfo path.
    415  * @param root Pointer to the root item or where to store
    416  *             a new root item (NULL for global sysinfo root).
    417  *
    418  */
    419 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    420 {
    421         /* Protect sysinfo tree consistency */
    422         ipl_t ipl = interrupts_disable();
    423         spinlock_lock(&sysinfo_lock);
    424        
    425         if (root == NULL)
    426                 root = &global_root;
    427        
    428         sysinfo_item_t *item = sysinfo_create_path(name, root);
     207       
    429208        if (item != NULL)
    430209                item->val_type = SYSINFO_VAL_UNDEFINED;
    431        
    432         spinlock_unlock(&sysinfo_lock);
    433         interrupts_restore(ipl);
    434 }
    435 
    436 /** Set sysinfo item with a generated subtree
    437  *
    438  * @param name Sysinfo path.
    439  * @param root Pointer to the root item or where to store
    440  *             a new root item (NULL for global sysinfo root).
    441  * @param fn   Subtree generator function.
    442  *
    443  */
    444 void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
    445     sysinfo_fn_subtree_t fn)
    446 {
    447         /* Protect sysinfo tree consistency */
    448         ipl_t ipl = interrupts_disable();
    449         spinlock_lock(&sysinfo_lock);
    450        
    451         if (root == NULL)
    452                 root = &global_root;
    453        
    454         sysinfo_item_t *item = sysinfo_create_path(name, root);
    455        
    456         /* Change the type of the subtree only if it is not already
    457            a fixed subtree */
    458         if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
    459                 item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
    460                 item->subtree.get_data = fn;
    461         }
    462        
    463         spinlock_unlock(&sysinfo_lock);
    464         interrupts_restore(ipl);
    465 }
    466 
    467 /** Sysinfo dump indentation helper routine
    468  *
    469  * @param depth Number of indentation characters to print.
    470  *
    471  */
    472 static void sysinfo_indent(unsigned int depth)
    473 {
    474         unsigned int i;
    475         for (i = 0; i < depth; i++)
    476                 printf("  ");
    477 }
    478 
    479 /** Dump the structure of sysinfo tree
    480  *
    481  * Should be called with interrupts disabled
    482  * and sysinfo_lock held. Because this routine
    483  * might take a reasonable long time to proceed,
    484  * having the spinlock held is not optimal, but
    485  * there is no better simple solution.
    486  *
    487  * @param root  Root item of the current (sub)tree.
    488  * @param depth Current depth in the sysinfo tree.
    489  *
    490  */
    491 static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
    492 {
    493         sysinfo_item_t *cur = root;
    494        
    495         /* Walk all siblings */
    496         while (cur != NULL) {
    497                 sysinfo_indent(depth);
    498                
    499                 unative_t val;
    500                 size_t size;
    501                
    502                 /* Display node value and type */
    503                 switch (cur->val_type) {
     210}
     211
     212
     213void sysinfo_dump(sysinfo_item_t **proot, int depth)
     214{
     215        sysinfo_item_t *root;
     216        if (proot == NULL)
     217                proot = &_root;
     218       
     219        root = *proot;
     220       
     221        while (root != NULL) {
     222                int i;
     223                unative_t val = 0;
     224                const char *vtype = NULL;
     225               
     226               
     227                for (i = 0; i < depth; i++)
     228                        printf("  ");
     229               
     230                switch (root->val_type) {
    504231                case SYSINFO_VAL_UNDEFINED:
    505                         printf("+ %s\n", cur->name);
     232                        val = 0;
     233                        vtype = "UND";
    506234                        break;
    507235                case SYSINFO_VAL_VAL:
    508                         printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
    509                             cur->val.val, cur->val.val);
     236                        val = root->val.val;
     237                        vtype = "VAL";
    510238                        break;
    511                 case SYSINFO_VAL_DATA:
    512                         printf("+ %s (%" PRIs" bytes)\n", cur->name,
    513                             cur->val.data.size);
    514                         break;
    515                 case SYSINFO_VAL_FUNCTION_VAL:
    516                         val = cur->val.fn_val(cur);
    517                         printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
    518                             cur->name, val, val);
    519                         break;
    520                 case SYSINFO_VAL_FUNCTION_DATA:
    521                         /* N.B.: No data was actually returned (only a dry run) */
    522                         (void) cur->val.fn_data(cur, &size, true);
    523                         printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
    524                             size);
    525                         break;
    526                 default:
    527                         printf("+ %s [unknown]\n", cur->name);
    528                 }
    529                
    530                 /* Recursivelly nest into the subtree */
    531                 switch (cur->subtree_type) {
    532                 case SYSINFO_SUBTREE_NONE:
    533                         break;
    534                 case SYSINFO_SUBTREE_TABLE:
    535                         sysinfo_dump_internal(cur->subtree.table, depth + 1);
    536                         break;
    537                 case SYSINFO_SUBTREE_FUNCTION:
    538                         sysinfo_indent(depth + 1);
    539                         printf("+ [generated subtree]\n");
    540                         break;
    541                 default:
    542                         sysinfo_indent(depth + 1);
    543                         printf("+ [unknown subtree]\n");
    544                 }
    545                
    546                 cur = cur->next;
    547         }
    548 }
    549 
    550 /** Dump the structure of sysinfo tree
    551  *
    552  * @param root  Root item of the sysinfo (sub)tree.
    553  *              If it is NULL then consider the global
    554  *              sysinfo tree.
    555  *
    556  */
    557 void sysinfo_dump(sysinfo_item_t *root)
    558 {
    559         /* Avoid other functions to mess with sysinfo
    560            while we are dumping it */
    561         ipl_t ipl = interrupts_disable();
    562         spinlock_lock(&sysinfo_lock);
    563        
    564         if (root == NULL)
    565                 sysinfo_dump_internal(global_root, 0);
    566         else
    567                 sysinfo_dump_internal(root, 0);
    568        
    569         spinlock_unlock(&sysinfo_lock);
    570         interrupts_restore(ipl);
    571 }
    572 
    573 /** Return sysinfo item value determined by name
    574  *
    575  * Should be called with interrupts disabled
    576  * and sysinfo_lock held.
    577  *
    578  * @param name    Sysinfo path.
    579  * @param root    Root item of the sysinfo (sub)tree.
    580  *                If it is NULL then consider the global
    581  *                sysinfo tree.
    582  * @param dry_run Do not actually get any generated
    583  *                binary data, just calculate the size.
    584  *
    585  * @return Item value (constant or generated).
    586  *
    587  */
    588 static sysinfo_return_t sysinfo_get_item(const char *name,
    589     sysinfo_item_t **root, bool dry_run)
    590 {
    591         if (root == NULL)
    592                 root = &global_root;
    593        
    594         /* Try to find the item or generate data */
    595         sysinfo_return_t ret;
    596         sysinfo_return_t *ret_ptr = &ret;
    597         sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
    598             dry_run);
    599        
    600         if (item != NULL) {
    601                 /* Item found in the fixed sysinfo tree */
    602                
    603                 ret.tag = item->val_type;
    604                 switch (item->val_type) {
    605                 case SYSINFO_VAL_UNDEFINED:
    606                         break;
    607                 case SYSINFO_VAL_VAL:
    608                         ret.val = item->val.val;
    609                         break;
    610                 case SYSINFO_VAL_DATA:
    611                         ret.data = item->val.data;
    612                         break;
    613                 case SYSINFO_VAL_FUNCTION_VAL:
    614                         ret.val = item->val.fn_val(item);
    615                         break;
    616                 case SYSINFO_VAL_FUNCTION_DATA:
    617                         ret.data.data = item->val.fn_data(item, &ret.data.size,
    618                             dry_run);
     239                case SYSINFO_VAL_FUNCTION:
     240                        val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
     241                        vtype = "FUN";
    619242                        break;
    620243                }
    621         } else {
    622                 /* No item in the fixed sysinfo tree */
    623                 if (ret_ptr == NULL) {
    624                         /* Even no data was generated */
    625                         ret.tag = SYSINFO_VAL_UNDEFINED;
    626                 }
    627         }
    628        
     244               
     245                printf("%s    %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val,
     246                        val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
     247                        "NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
     248                        "TAB" : "FUN"));
     249               
     250                if (root->subinfo_type == SYSINFO_SUBINFO_TABLE)
     251                        sysinfo_dump(&(root -> subinfo.table), depth + 1);
     252               
     253                root = root->next;
     254        }
     255}
     256
     257sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root)
     258{
     259        // TODO: Implement Subsystem subinfo (by function implemented subinfo)
     260
     261        sysinfo_rettype_t ret = {0, false};
     262
     263        if (root == NULL)
     264                root = &_root;
     265       
     266        sysinfo_item_t *item = sysinfo_find_item(name, *root);
     267       
     268        if (item != NULL) {
     269                if (item->val_type == SYSINFO_VAL_UNDEFINED)
     270                        return ret;
     271                else
     272                        ret.valid = true;
     273               
     274                if (item->val_type == SYSINFO_VAL_VAL)
     275                        ret.val = item->val.val;
     276                else
     277                        ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
     278        }
    629279        return ret;
    630280}
    631281
    632 /** Return sysinfo item determined by name from user space
    633  *
    634  * Should be called with interrupts disabled
    635  * and sysinfo_lock held. The path string passed from
    636  * the user space has to be properly null-terminated
    637  * (the last passed character must be null).
    638  *
    639  * @param ptr     Sysinfo path in the user address space.
    640  * @param size    Size of the path string.
    641  * @param dry_run Do not actually get any generated
    642  *                binary data, just calculate the size.
    643  *
    644  */
    645 static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
    646     bool dry_run)
    647 {
    648         sysinfo_return_t ret;
    649         ret.tag = SYSINFO_VAL_UNDEFINED;
    650        
    651         if (size > SYSINFO_MAX_PATH)
    652                 return ret;
    653        
    654         char *path = (char *) malloc(size + 1, 0);
    655         ASSERT(path);
    656        
    657         if ((copy_from_uspace(path, ptr, size + 1) == 0)
    658             && (path[size] == 0))
    659                 ret = sysinfo_get_item(path, NULL, dry_run);
    660        
    661         free(path);
    662         return ret;
    663 }
    664 
    665 /** Get the sysinfo value type (syscall)
    666  *
    667  * The path string passed from the user space has
    668  * to be properly null-terminated (the last passed
    669  * character must be null).
    670  *
    671  * @param path_ptr  Sysinfo path in the user address space.
    672  * @param path_size Size of the path string.
    673  *
    674  * @return Item value type.
    675  *
    676  */
    677 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
    678 {
    679         /* Avoid other functions to mess with sysinfo
    680            while we are reading it */
    681         ipl_t ipl = interrupts_disable();
    682         spinlock_lock(&sysinfo_lock);
    683        
    684         /* Get the item.
    685        
    686            N.B.: There is no need to free any potential generated
    687            binary data since we request a dry run */
    688         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
    689        
    690         /* Map generated value types to constant types
    691            (user space does not care whether the
    692            value is constant or generated) */
    693         if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
    694                 ret.tag = SYSINFO_VAL_VAL;
    695         else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
    696                 ret.tag = SYSINFO_VAL_DATA;
    697        
    698         spinlock_unlock(&sysinfo_lock);
    699         interrupts_restore(ipl);
    700        
    701         return (unative_t) ret.tag;
    702 }
    703 
    704 /** Get the sysinfo numerical value (syscall)
    705  *
    706  * The path string passed from the user space has
    707  * to be properly null-terminated (the last passed
    708  * character must be null).
    709  *
    710  * @param path_ptr  Sysinfo path in the user address space.
    711  * @param path_size Size of the path string.
    712  * @param value_ptr User space pointer where to store the
    713  *                  numberical value.
    714  *
    715  * @return Error code (EOK in case of no error).
    716  *
    717  */
    718 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
    719     void *value_ptr)
    720 {
    721         /* Avoid other functions to mess with sysinfo
    722            while we are reading it */
    723         ipl_t ipl = interrupts_disable();
    724         spinlock_lock(&sysinfo_lock);
    725        
    726         /* Get the item.
    727        
    728            N.B.: There is no need to free any potential generated
    729            binary data since we request a dry run */
    730         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
    731         int rc;
    732        
    733         /* Only constant or generated numerical value is returned */
    734         if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
    735                 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
    736         else
    737                 rc = EINVAL;
    738        
    739         spinlock_unlock(&sysinfo_lock);
    740         interrupts_restore(ipl);
    741        
    742         return (unative_t) rc;
    743 }
    744 
    745 /** Get the sysinfo binary data size (syscall)
    746  *
    747  * The path string passed from the user space has
    748  * to be properly null-terminated (the last passed
    749  * character must be null).
    750  *
    751  * @param path_ptr  Sysinfo path in the user address space.
    752  * @param path_size Size of the path string.
    753  * @param size_ptr  User space pointer where to store the
    754  *                  binary data size.
    755  *
    756  * @return Error code (EOK in case of no error).
    757  *
    758  */
    759 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
    760     void *size_ptr)
    761 {
    762         /* Avoid other functions to mess with sysinfo
    763            while we are reading it */
    764         ipl_t ipl = interrupts_disable();
    765         spinlock_lock(&sysinfo_lock);
    766        
    767         /* Get the item.
    768        
    769            N.B.: There is no need to free any potential generated
    770            binary data since we request a dry run */
    771         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
    772         int rc;
    773        
    774         /* Only the size of constant or generated binary data is considered */
    775         if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
    776                 rc = copy_to_uspace(size_ptr, &ret.data.size,
    777                     sizeof(ret.data.size));
    778         else
    779                 rc = EINVAL;
    780        
    781         spinlock_unlock(&sysinfo_lock);
    782         interrupts_restore(ipl);
    783        
    784         return (unative_t) rc;
    785 }
    786 
    787 /** Get the sysinfo binary data (syscall)
    788  *
    789  * The path string passed from the user space has
    790  * to be properly null-terminated (the last passed
    791  * character must be null).
    792  *
    793  * The user space buffer must be sized exactly according
    794  * to the size of the binary data, otherwise the request
    795  * fails.
    796  *
    797  * @param path_ptr    Sysinfo path in the user address space.
    798  * @param path_size   Size of the path string.
    799  * @param buffer_ptr  User space pointer to the buffer where
    800  *                    to store the binary data.
    801  * @param buffer_size User space buffer size.
    802  *
    803  * @return Error code (EOK in case of no error).
    804  *
    805  */
    806 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
    807     void *buffer_ptr, size_t buffer_size)
    808 {
    809         /* Avoid other functions to mess with sysinfo
    810            while we are reading it */
    811         ipl_t ipl = interrupts_disable();
    812         spinlock_lock(&sysinfo_lock);
    813        
    814         /* Get the item */
    815         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, false);
    816         int rc;
    817        
    818         /* Only constant or generated binary data is considered */
    819         if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
    820                 /* Check destination buffer size */
    821                 if (ret.data.size == buffer_size)
    822                         rc = copy_to_uspace(buffer_ptr, ret.data.data,
    823                             ret.data.size);
    824                 else
    825                         rc = ENOMEM;
    826         } else
    827                 rc = EINVAL;
    828        
    829         /* N.B.: The generated binary data should be freed */
    830         if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
    831                 free(ret.data.data);
    832        
    833         spinlock_unlock(&sysinfo_lock);
    834         interrupts_restore(ipl);
    835        
    836         return (unative_t) rc;
     282#define SYSINFO_MAX_LEN 1024
     283
     284unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
     285{
     286        char *str;
     287        sysinfo_rettype_t ret = {0, 0};
     288
     289        if (len > SYSINFO_MAX_LEN)
     290                return ret.valid;
     291        str = malloc(len + 1, 0);
     292       
     293        ASSERT(str);
     294        if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
     295                ret = sysinfo_get_val(str, NULL);
     296       
     297        free(str);
     298        return ret.valid;
     299}
     300
     301unative_t sys_sysinfo_value(unative_t ptr, unative_t len)
     302{
     303        char *str;
     304        sysinfo_rettype_t ret = {0, 0};
     305       
     306        if (len > SYSINFO_MAX_LEN)
     307                return ret.val;
     308        str = malloc(len + 1, 0);
     309       
     310        ASSERT(str);
     311        if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
     312                ret = sysinfo_get_val(str, NULL);
     313       
     314        free(str);
     315        return ret.val;
    837316}
    838317
Note: See TracChangeset for help on using the changeset viewer.