Ignore:
File:
1 edited

Legend:

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

    rb658c5d r137691a  
    3737#include <print.h>
    3838#include <syscall/copy.h>
    39 #include <errno.h>
    40 
    41 #define SYSINFO_MAX_PATH  2048
    4239
    4340bool fb_exported = false;
    44 
    45 static sysinfo_item_t *global_root = NULL;
    46 static slab_cache_t *sysinfo_item_slab;
    47 
    48 static int sysinfo_item_constructor(void *obj, int kmflag)
    49 {
    50         sysinfo_item_t *item = (sysinfo_item_t *) obj;
    51        
    52         item->name = NULL;
    53         item->val_type = SYSINFO_VAL_UNDEFINED;
    54         item->subtree_type = SYSINFO_SUBTREE_NONE;
    55         item->subtree.table = NULL;
    56         item->next = NULL;
    57        
    58         return 0;
    59 }
    60 
    61 static int sysinfo_item_destructor(void *obj)
    62 {
    63         sysinfo_item_t *item = (sysinfo_item_t *) obj;
    64        
    65         if (item->name != NULL)
    66                 free(item->name);
    67        
    68         return 0;
    69 }
    70 
    71 void sysinfo_init(void)
    72 {
    73         sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
    74             sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
    75             sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
    76 }
    77 
    78 static sysinfo_item_t *sysinfo_find_item(const char *name,
    79     sysinfo_item_t *subtree)
    80 {
    81         sysinfo_item_t *cur = subtree;
    82        
    83         while (cur != NULL) {
    84                 size_t i = 0;
    85                
    86                 /* Compare name with path */
    87                 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]))
    8854                        i++;
    8955               
    90                 /* Check for perfect name and path match */
    91                 if ((name[i] == 0) && (cur->name[i] == 0))
    92                         return cur;
    93                
    94                 /* Partial match up to the delimiter */
    95                 if ((name[i] == '.') && (cur->name[i] == 0)) {
    96                         /* Look into the subtree */
    97                         switch (cur->subtree_type) {
    98                         case SYSINFO_SUBTREE_TABLE:
    99                                 /* Recursively find in subtree */
    100                                 return sysinfo_find_item(name + i + 1, cur->subtree.table);
    101                         case SYSINFO_SUBTREE_FUNCTION:
    102                                 /* Get generated item */
    103                                 return cur->subtree.find_item(name + i + 1);
    104                         default:
    105                                 /* Not found */
    106                                 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));
    107125                        }
     126                       
     127                        //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
     128                        //      return NULL;
     129                       
     130                        return NULL;
    108131                }
    109                
    110                 cur = cur->next;
    111         }
    112        
     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.");
    113165        return NULL;
    114166}
    115167
    116 static sysinfo_item_t *sysinfo_create_path(const char *name,
    117     sysinfo_item_t **psubtree)
    118 {
    119         ASSERT(psubtree != NULL);
    120        
    121         if (*psubtree == NULL) {
    122                 /* No parent */
    123                
    124                 size_t i = 0;
    125                
    126                 /* Find the first delimiter in name */
    127                 while ((name[i] != 0) && (name[i] != '.'))
    128                         i++;
    129                
    130                 *psubtree =
    131                     (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
    132                 ASSERT(*psubtree);
    133                
    134                 /* Fill in item name up to the delimiter */
    135                 (*psubtree)->name = str_ndup(name, i);
    136                 ASSERT((*psubtree)->name);
    137                
    138                 /* Create subtree items */
    139                 if (name[i] == '.') {
    140                         (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
    141                         return sysinfo_create_path(name + i + 1,
    142                             &((*psubtree)->subtree.table));
    143                 }
    144                
    145                 /* No subtree needs to be created */
    146                 return *psubtree;
    147         }
    148        
    149         sysinfo_item_t *cur = *psubtree;
    150        
    151         while (cur != NULL) {
    152                 size_t i = 0;
    153                
    154                 /* Compare name with path */
    155                 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
    156                         i++;
    157                
    158                 /* Check for perfect name and path match
    159                  * -> item is already present.
    160                  */
    161                 if ((name[i] == 0) && (cur->name[i] == 0))
    162                         return cur;
    163                
    164                 /* Partial match up to the delimiter */
    165                 if ((name[i] == '.') && (cur->name[i] == 0)) {
    166                         switch (cur->subtree_type) {
    167                         case SYSINFO_SUBTREE_NONE:
    168                                 /* No subtree yet, create one */
    169                                 cur->subtree_type = SYSINFO_SUBTREE_TABLE;
    170                                 return sysinfo_create_path(name + i + 1,
    171                                     &(cur->subtree.table));
    172                         case SYSINFO_SUBTREE_TABLE:
    173                                 /* Subtree already created, add new sibling */
    174                                 return sysinfo_create_path(name + i + 1,
    175                                     &(cur->subtree.table));
    176                         default:
    177                                 /* Subtree items handled by a function, this
    178                                  * cannot be overriden.
    179                                  */
    180                                 return NULL;
    181                         }
    182                 }
    183                
    184                 /* No match and no more siblings to check
    185                  * -> create a new sibling item.
    186                  */
    187                 if (cur->next == NULL) {
    188                         /* Find the first delimiter in name */
    189                         i = 0;
    190                         while ((name[i] != 0) && (name[i] != '.'))
    191                                 i++;
    192                        
    193                         sysinfo_item_t *item =
    194                             (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
    195                         ASSERT(item);
    196                        
    197                         cur->next = item;
    198                        
    199                         /* Fill in item name up to the delimiter */
    200                         item->name = str_ndup(name, i);
    201                         ASSERT(item->name);
    202                        
    203                         /* Create subtree items */
    204                         if (name[i] == '.') {
    205                                 item->subtree_type = SYSINFO_SUBTREE_TABLE;
    206                                 return sysinfo_create_path(name + i + 1,
    207                                     &(item->subtree.table));
    208                         }
    209                        
    210                         /* No subtree needs to be created */
    211                         return item;
    212                 }
    213                
    214                 /* Get next sibling */
    215                 cur = cur->next;
    216         }
    217        
    218         /* Unreachable */
    219         ASSERT(false);
    220         return NULL;
    221 }
    222 
    223 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
    224     unative_t val)
     168void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
    225169{
    226170        if (root == NULL)
    227                 root = &global_root;
    228        
     171                root = &_root;
     172       
     173        /* If already created create only returns pointer
     174           If not, create it */
    229175        sysinfo_item_t *item = sysinfo_create_path(name, root);
    230         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;                   
    231179                item->val_type = SYSINFO_VAL_VAL;
    232                 item->val.val = val;
    233         }
    234 }
    235 
    236 void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
    237     void *data, size_t size)
     180        }
     181}
     182
     183void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
    238184{
    239185        if (root == NULL)
    240                 root = &global_root;
    241        
     186                root = &_root;
     187       
     188        /* If already created create only returns pointer
     189           If not, create it */
    242190        sysinfo_item_t *item = sysinfo_create_path(name, root);
    243         if (item != NULL) {
    244                 item->val_type = SYSINFO_VAL_DATA;
    245                 item->val.data.data = data;
    246                 item->val.data.size = size;
    247         }
    248 }
    249 
    250 void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root,
    251     sysinfo_fn_val_t fn)
     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)
    252200{
    253201        if (root == NULL)
    254                 root = &global_root;
    255        
     202                root = &_root;
     203       
     204        /* If already created create only returns pointer
     205           If not, create it */
    256206        sysinfo_item_t *item = sysinfo_create_path(name, root);
    257         if (item != NULL) {
    258                 item->val_type = SYSINFO_VAL_FUNCTION_VAL;
    259                 item->val.fn_val = fn;
    260         }
    261 }
    262 
    263 void sysinfo_set_item_data_fn(const char *name, sysinfo_item_t **root,
    264     sysinfo_fn_data_t fn)
    265 {
    266         if (root == NULL)
    267                 root = &global_root;
    268        
    269         sysinfo_item_t *item = sysinfo_create_path(name, root);
    270         if (item != NULL) {
    271                 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
    272                 item->val.fn_data = fn;
    273         }
    274 }
    275 
    276 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    277 {
    278         if (root == NULL)
    279                 root = &global_root;
    280        
    281         sysinfo_item_t *item = sysinfo_create_path(name, root);
     207       
    282208        if (item != NULL)
    283209                item->val_type = SYSINFO_VAL_UNDEFINED;
    284210}
    285211
    286 static void sysinfo_indent(unsigned int depth)
    287 {
    288         unsigned int i;
    289         for (i = 0; i < depth; i++)
    290                 printf("  ");
    291 }
    292 
    293 void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth)
    294 {
     212
     213void sysinfo_dump(sysinfo_item_t **proot, int depth)
     214{
     215        sysinfo_item_t *root;
    295216        if (proot == NULL)
    296                 proot = &global_root;
    297        
    298         sysinfo_item_t *cur = *proot;
    299        
    300         while (cur != NULL) {
    301                 sysinfo_indent(depth);
    302                
    303                 unative_t val;
    304                 size_t size;
    305                
    306                 switch (cur->val_type) {
     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) {
    307231                case SYSINFO_VAL_UNDEFINED:
    308                         printf("+ %s\n", cur->name);
     232                        val = 0;
     233                        vtype = "UND";
    309234                        break;
    310235                case SYSINFO_VAL_VAL:
    311                         printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
    312                             cur->val.val, cur->val.val);
     236                        val = root->val.val;
     237                        vtype = "VAL";
    313238                        break;
    314                 case SYSINFO_VAL_DATA:
    315                         printf("+ %s (%" PRIs" bytes)\n", cur->name,
    316                             cur->val.data.size);
    317                         break;
    318                 case SYSINFO_VAL_FUNCTION_VAL:
    319                         val = cur->val.fn_val(cur);
    320                         printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
    321                             cur->name, val, val);
    322                         break;
    323                 case SYSINFO_VAL_FUNCTION_DATA:
    324                         cur->val.fn_data(cur, &size);
    325                         printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
    326                             size);
    327                         break;
    328                 default:
    329                         printf("+ %s [unknown]\n", cur->name);
    330                 }
    331                
    332                 switch (cur->subtree_type) {
    333                 case SYSINFO_SUBTREE_NONE:
    334                         break;
    335                 case SYSINFO_SUBTREE_TABLE:
    336                         sysinfo_dump(&(cur->subtree.table), depth + 1);
    337                         break;
    338                 case SYSINFO_SUBTREE_FUNCTION:
    339                         sysinfo_indent(depth + 1);
    340                         printf("  [generated subtree]\n");
    341                         break;
    342                 default:
    343                         sysinfo_indent(depth + 1);
    344                         printf("  [unknown subtree]\n");
    345                 }
    346                
    347                 cur = cur->next;
    348         }
    349 }
    350 
    351 sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root)
    352 {
    353         if (root == NULL)
    354                 root = &global_root;
    355        
    356         sysinfo_item_t *item = sysinfo_find_item(name, *root);
    357         sysinfo_return_t ret;
    358        
    359         if (item != NULL) {
    360                 switch (item->val_type) {
    361                 case SYSINFO_VAL_UNDEFINED:
    362                         ret.tag = SYSINFO_VAL_UNDEFINED;
    363                         break;
    364                 case SYSINFO_VAL_VAL:
    365                         ret.tag = SYSINFO_VAL_VAL;
    366                         ret.val = item->val.val;
    367                         break;
    368                 case SYSINFO_VAL_DATA:
    369                         ret.tag = SYSINFO_VAL_DATA;
    370                         ret.data = item->val.data;
    371                         break;
    372                 case SYSINFO_VAL_FUNCTION_VAL:
    373                         ret.tag = SYSINFO_VAL_VAL;
    374                         ret.val = item->val.fn_val(item);
    375                         break;
    376                 case SYSINFO_VAL_FUNCTION_DATA:
    377                         ret.tag = SYSINFO_VAL_DATA;
    378                         ret.data.data = item->val.fn_data(item, &ret.data.size);
     239                case SYSINFO_VAL_FUNCTION:
     240                        val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
     241                        vtype = "FUN";
    379242                        break;
    380243                }
    381         } else
    382                 ret.tag = SYSINFO_VAL_UNDEFINED;
    383        
     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        }
    384279        return ret;
    385280}
    386281
    387 static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size)
    388 {
    389         sysinfo_return_t ret;
    390         ret.tag = SYSINFO_VAL_UNDEFINED;
    391        
    392         if (size > SYSINFO_MAX_PATH)
    393                 return ret;
    394        
    395         char *path = (char *) malloc(size + 1, 0);
    396         ASSERT(path);
    397        
    398         if ((copy_from_uspace(path, ptr, size + 1) == 0)
    399             && (path[size] == 0)) {
    400                 ret = sysinfo_get_item(path, NULL);
    401                 free(path);
    402         }
    403        
    404         return ret;
    405 }
    406 
    407 unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
    408 {
    409         return (unative_t) sysinfo_get_item_uspace(path_ptr, path_size).tag;
    410 }
    411 
    412 unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
    413     void *value_ptr)
    414 {
    415         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
    416        
    417         if (ret.tag != SYSINFO_VAL_VAL)
    418                 return (unative_t) EINVAL;
    419        
    420         return (unative_t) copy_to_uspace(value_ptr, &ret.val,
    421             sizeof(ret.val));
    422 }
    423 
    424 unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
    425     void *size_ptr)
    426 {
    427         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
    428        
    429         if (ret.tag != SYSINFO_VAL_DATA)
    430                 return (unative_t) EINVAL;
    431        
    432         return (unative_t) copy_to_uspace(size_ptr, &ret.data.size,
    433             sizeof(ret.data.size));
    434 }
    435 
    436 unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
    437     void *buffer_ptr, size_t buffer_size)
    438 {
    439         sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
    440        
    441         if (ret.tag != SYSINFO_VAL_DATA)
    442                 return (unative_t) EINVAL;
    443        
    444         if (ret.data.size != buffer_size)
    445                 return ENOMEM;
    446        
    447         return (unative_t) copy_to_uspace(buffer_ptr, ret.data.data,
    448             ret.data.size);
     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;
    449316}
    450317
Note: See TracChangeset for help on using the changeset viewer.