Ignore:
File:
1 edited

Legend:

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

    r137691a rb658c5d  
    3737#include <print.h>
    3838#include <syscall/copy.h>
     39#include <errno.h>
     40
     41#define SYSINFO_MAX_PATH  2048
    3942
    4043bool fb_exported = false;
    41 sysinfo_item_t *_root = NULL;
    42 
    43 static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree)
    44 {
    45         if (subtree == NULL)
    46                 return NULL;
    47        
    48         while (subtree != NULL) {
    49                 int i = 0;
    50                 char *a = (char *) name;
    51                 char *b = subtree->name;
    52                
    53                 while ((a[i] == b[i]) && (b[i]))
     44
     45static sysinfo_item_t *global_root = NULL;
     46static slab_cache_t *sysinfo_item_slab;
     47
     48static 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
     61static 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
     71void 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
     78static 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]))
    5488                        i++;
    5589               
    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);
     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;
     107                        }
     108                }
     109               
     110                cur = cur->next;
     111        }
     112       
     113        return NULL;
     114}
     115
     116static 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++;
    62192                       
    63                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    64                         //      return NULL;
     193                        sysinfo_item_t *item =
     194                            (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
     195                        ASSERT(item);
    65196                       
    66                         return NULL; /* No subinfo */
    67                 }
    68                 /* No matches try next */
    69                 subtree = subtree->next;
    70         }
    71         return NULL;
    72 }
    73 
    74 static 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;
     197                        cur->next = item;
    82198                       
    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++;
     199                        /* Fill in item name up to the delimiter */
     200                        item->name = str_ndup(name, i);
     201                        ASSERT(item->name);
    91202                       
    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));
     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));
    125208                        }
    126209                       
    127                         //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
    128                         //      return NULL;
    129                        
    130                         return NULL;
    131                 }
    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;
     210                        /* No subtree needs to be created */
    159211                        return item;
    160                 } else
    161                         subtree = subtree->next;
    162         }
    163 
    164         panic("Not reached.");
     212                }
     213               
     214                /* Get next sibling */
     215                cur = cur->next;
     216        }
     217       
     218        /* Unreachable */
     219        ASSERT(false);
    165220        return NULL;
    166221}
    167222
    168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
    169 {
    170         if (root == NULL)
    171                 root = &_root;
    172        
    173         /* If already created create only returns pointer
    174            If not, create it */
     223void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
     224    unative_t val)
     225{
     226        if (root == NULL)
     227                root = &global_root;
     228       
    175229        sysinfo_item_t *item = sysinfo_create_path(name, root);
    176        
    177         if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
    178                 item->val.val = val;                   
     230        if (item != NULL) {
    179231                item->val_type = SYSINFO_VAL_VAL;
    180         }
    181 }
    182 
    183 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
    184 {
    185         if (root == NULL)
    186                 root = &_root;
    187        
    188         /* If already created create only returns pointer
    189            If not, create it */
     232                item->val.val = val;
     233        }
     234}
     235
     236void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
     237    void *data, size_t size)
     238{
     239        if (root == NULL)
     240                root = &global_root;
     241       
    190242        sysinfo_item_t *item = sysinfo_create_path(name, root);
    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 
     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
     250void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root,
     251    sysinfo_fn_val_t fn)
     252{
     253        if (root == NULL)
     254                root = &global_root;
     255       
     256        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
     263void 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}
    198275
    199276void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
    200277{
    201278        if (root == NULL)
    202                 root = &_root;
    203        
    204         /* If already created create only returns pointer
    205            If not, create it */
     279                root = &global_root;
     280       
    206281        sysinfo_item_t *item = sysinfo_create_path(name, root);
    207        
    208282        if (item != NULL)
    209283                item->val_type = SYSINFO_VAL_UNDEFINED;
    210284}
    211285
    212 
    213 void sysinfo_dump(sysinfo_item_t **proot, int depth)
    214 {
    215         sysinfo_item_t *root;
     286static void sysinfo_indent(unsigned int depth)
     287{
     288        unsigned int i;
     289        for (i = 0; i < depth; i++)
     290                printf("  ");
     291}
     292
     293void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth)
     294{
    216295        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) {
     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) {
    231307                case SYSINFO_VAL_UNDEFINED:
    232                         val = 0;
    233                         vtype = "UND";
     308                        printf("+ %s\n", cur->name);
    234309                        break;
    235310                case SYSINFO_VAL_VAL:
    236                         val = root->val.val;
    237                         vtype = "VAL";
    238                         break;
    239                 case SYSINFO_VAL_FUNCTION:
    240                         val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
    241                         vtype = "FUN";
    242                         break;
    243                 }
    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 
    257 sysinfo_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;
     311                        printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
     312                            cur->val.val, cur->val.val);
     313                        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
     351sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root)
     352{
     353        if (root == NULL)
     354                root = &global_root;
    265355       
    266356        sysinfo_item_t *item = sysinfo_find_item(name, *root);
     357        sysinfo_return_t ret;
    267358       
    268359        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)
     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;
    275366                        ret.val = item->val.val;
    276                 else
    277                         ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
    278         }
     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);
     379                        break;
     380                }
     381        } else
     382                ret.tag = SYSINFO_VAL_UNDEFINED;
     383       
    279384        return ret;
    280385}
    281386
    282 #define SYSINFO_MAX_LEN 1024
    283 
    284 unative_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 
    301 unative_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;
     387static 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
     407unative_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
     412unative_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
     424unative_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
     436unative_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);
    316449}
    317450
Note: See TracChangeset for help on using the changeset viewer.