Ignore:
File:
1 edited

Legend:

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

    rf97f1e51 r9a426d1f  
    11/*
    22 * Copyright (c) 2006 Jakub Vana
    3  * Copyright (c) 2012 Martin Decky
    43 * All rights reserved.
    54 *
     
    9796void sysinfo_init(void)
    9897{
    99         sysinfo_item_slab = slab_cache_create("sysinfo_item_t",
     98        sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
    10099            sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
    101100            sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
    102        
     101
    103102        mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE);
    104103}
     
    111110 * @param subtree Current sysinfo (sub)tree root item.
    112111 * @param ret     If the return value is NULL, this argument
    113  *                can be set either to NULL (i.e. no item was
     112 *                can be either also NULL (i.e. no item was
    114113 *                found and no data was generated) or the
    115114 *                original pointer is used to store the value
     
    126125{
    127126        ASSERT(subtree != NULL);
     127        ASSERT(ret != NULL);
    128128       
    129129        sysinfo_item_t *cur = subtree;
     
    151151                        case SYSINFO_SUBTREE_FUNCTION:
    152152                                /* Get generated data */
    153                                 if (ret != NULL)
    154                                         **ret = cur->subtree.generator.fn(name + i + 1,
    155                                             dry_run, cur->subtree.generator.data);
    156                                
     153                                **ret = cur->subtree.get_data(name + i + 1, dry_run);
    157154                                return NULL;
    158155                        default:
    159156                                /* Not found, no data generated */
    160                                 if (ret != NULL)
    161                                         *ret = NULL;
    162                                
     157                                *ret = NULL;
    163158                                return NULL;
    164159                        }
     
    169164       
    170165        /* Not found, no data generated */
    171         if (ret != NULL)
    172                 *ret = NULL;
    173        
     166        *ret = NULL;
    174167        return NULL;
    175168}
     
    359352 *             a new root item (NULL for global sysinfo root).
    360353 * @param fn   Numeric value generator function.
    361  * @param data Private data.
    362  *
    363  */
    364 void sysinfo_set_item_gen_val(const char *name, sysinfo_item_t **root,
    365     sysinfo_fn_val_t fn, void *data)
     354 *
     355 */
     356void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
     357    sysinfo_fn_val_t fn)
    366358{
    367359        /* Protect sysinfo tree consistency */
     
    374366        if (item != NULL) {
    375367                item->val_type = SYSINFO_VAL_FUNCTION_VAL;
    376                 item->val.gen_val.fn = fn;
    377                 item->val.gen_val.data = data;
     368                item->val.fn_val = fn;
    378369        }
    379370       
     
    392383 *             a new root item (NULL for global sysinfo root).
    393384 * @param fn   Binary data generator function.
    394  * @param data Private data.
    395  *
    396  */
    397 void sysinfo_set_item_gen_data(const char *name, sysinfo_item_t **root,
    398     sysinfo_fn_data_t fn, void *data)
     385 *
     386 */
     387void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
     388    sysinfo_fn_data_t fn)
    399389{
    400390        /* Protect sysinfo tree consistency */
     
    407397        if (item != NULL) {
    408398                item->val_type = SYSINFO_VAL_FUNCTION_DATA;
    409                 item->val.gen_data.fn = fn;
    410                 item->val.gen_data.data = data;
     399                item->val.fn_data = fn;
    411400        }
    412401       
     
    442431 *             a new root item (NULL for global sysinfo root).
    443432 * @param fn   Subtree generator function.
    444  * @param data Private data to be passed to the generator.
    445433 *
    446434 */
    447435void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
    448     sysinfo_fn_subtree_t fn, void *data)
     436    sysinfo_fn_subtree_t fn)
    449437{
    450438        /* Protect sysinfo tree consistency */
     
    460448        if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
    461449                item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
    462                 item->subtree.generator.fn = fn;
    463                 item->subtree.generator.data = data;
     450                item->subtree.get_data = fn;
    464451        }
    465452       
     
    469456/** Sysinfo dump indentation helper routine
    470457 *
    471  * @param depth Number of spaces to print.
    472  *
    473  */
    474 NO_TRACE static void sysinfo_indent(size_t spaces)
    475 {
    476         for (size_t i = 0; i < spaces; i++)
    477                 printf(" ");
     458 * @param depth Number of indentation characters to print.
     459 *
     460 */
     461NO_TRACE static void sysinfo_indent(unsigned int depth)
     462{
     463        unsigned int i;
     464        for (i = 0; i < depth; i++)
     465                printf("  ");
    478466}
    479467
     
    482470 * Should be called with sysinfo_lock held.
    483471 *
    484  * @param root   Root item of the current (sub)tree.
    485  * @param spaces Current indentation level.
    486  *
    487  */
    488 NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, size_t spaces)
    489 {
     472 * @param root  Root item of the current (sub)tree.
     473 * @param depth Current depth in the sysinfo tree.
     474 *
     475 */
     476NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
     477{
     478        sysinfo_item_t *cur = root;
     479       
    490480        /* Walk all siblings */
    491         for (sysinfo_item_t *cur = root; cur; cur = cur->next) {
    492                 size_t length;
    493                
    494                 if (spaces == 0) {
    495                         printf("%s", cur->name);
    496                         length = str_length(cur->name);
    497                 } else {
    498                         sysinfo_indent(spaces);
    499                         printf(".%s", cur->name);
    500                         length = str_length(cur->name) + 1;
    501                 }
     481        while (cur != NULL) {
     482                sysinfo_indent(depth);
    502483               
    503484                sysarg_t val;
     
    507488                switch (cur->val_type) {
    508489                case SYSINFO_VAL_UNDEFINED:
    509                         printf(" [undefined]\n");
     490                        printf("+ %s\n", cur->name);
    510491                        break;
    511492                case SYSINFO_VAL_VAL:
    512                         printf(" -> %" PRIun" (%#" PRIxn ")\n", cur->val.val,
    513                             cur->val.val);
     493                        printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
     494                            cur->val.val, cur->val.val);
    514495                        break;
    515496                case SYSINFO_VAL_DATA:
    516                         printf(" (%zu bytes)\n", cur->val.data.size);
     497                        printf("+ %s (%zu bytes)\n", cur->name,
     498                            cur->val.data.size);
    517499                        break;
    518500                case SYSINFO_VAL_FUNCTION_VAL:
    519                         val = cur->val.gen_val.fn(cur, cur->val.gen_val.data);
    520                         printf(" -> %" PRIun" (%#" PRIxn ") [generated]\n", val,
    521                             val);
     501                        val = cur->val.fn_val(cur);
     502                        printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
     503                            cur->name, val, val);
    522504                        break;
    523505                case SYSINFO_VAL_FUNCTION_DATA:
    524506                        /* N.B.: No data was actually returned (only a dry run) */
    525                         (void) cur->val.gen_data.fn(cur, &size, true,
    526                             cur->val.gen_data.data);
    527                         printf(" (%zu bytes) [generated]\n", size);
     507                        (void) cur->val.fn_data(cur, &size, true);
     508                        printf("+ %s (%zu bytes) [generated]\n", cur->name,
     509                            size);
    528510                        break;
    529511                default:
     
    536518                        break;
    537519                case SYSINFO_SUBTREE_TABLE:
    538                         sysinfo_dump_internal(cur->subtree.table, spaces + length);
     520                        sysinfo_dump_internal(cur->subtree.table, depth + 1);
    539521                        break;
    540522                case SYSINFO_SUBTREE_FUNCTION:
    541                         sysinfo_indent(spaces + length);
    542                         printf("<generated subtree>\n");
     523                        sysinfo_indent(depth + 1);
     524                        printf("+ [generated subtree]\n");
    543525                        break;
    544526                default:
    545                         sysinfo_indent(spaces + length);
    546                         printf("<unknown subtree>\n");
     527                        sysinfo_indent(depth + 1);
     528                        printf("+ [unknown subtree]\n");
    547529                }
     530               
     531                cur = cur->next;
    548532        }
    549533}
     
    610594                        break;
    611595                case SYSINFO_VAL_FUNCTION_VAL:
    612                         ret.val = item->val.gen_val.fn(item, item->val.gen_val.data);
     596                        ret.val = item->val.fn_val(item);
    613597                        break;
    614598                case SYSINFO_VAL_FUNCTION_DATA:
    615                         ret.data.data = item->val.gen_data.fn(item, &ret.data.size,
    616                             dry_run, item->val.gen_data.data);
     599                        ret.data.data = item->val.fn_data(item, &ret.data.size,
     600                            dry_run);
    617601                        break;
    618602                }
     
    651635        ASSERT(path);
    652636       
    653         if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
    654             (path[size] == 0)) {
     637        if ((copy_from_uspace(path, ptr, size + 1) == 0)
     638            && (path[size] == 0)) {
    655639                /*
    656640                 * Prevent other functions from messing with sysinfo while we
     
    661645                mutex_unlock(&sysinfo_lock);
    662646        }
    663        
    664647        free(path);
    665648        return ret;
    666 }
    667 
    668 /** Return sysinfo keys determined by name
    669  *
    670  * Should be called with sysinfo_lock held.
    671  *
    672  * @param name    Sysinfo path.
    673  * @param root    Root item of the sysinfo (sub)tree.
    674  *                If it is NULL then consider the global
    675  *                sysinfo tree.
    676  * @param dry_run Do not actually get any generated
    677  *                binary data, just calculate the size.
    678  *
    679  * @return Item value (constant or generated).
    680  *
    681  */
    682 NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
    683     sysinfo_item_t **root, bool dry_run)
    684 {
    685         if (root == NULL)
    686                 root = &global_root;
    687        
    688         sysinfo_item_t *subtree = NULL;
    689        
    690         if (name[0] != 0) {
    691                 /* Try to find the item */
    692                 sysinfo_item_t *item =
    693                     sysinfo_find_item(name, *root, NULL, dry_run);
    694                 if ((item != NULL) &&
    695                     (item->subtree_type == SYSINFO_SUBTREE_TABLE))
    696                         subtree = item->subtree.table;
    697         } else
    698                 subtree = *root;
    699        
    700         sysinfo_return_t ret;
    701        
    702         if (subtree != NULL) {
    703                 /*
    704                  * Calculate the size of subkeys.
    705                  */
    706                 size_t size = 0;
    707                 for (sysinfo_item_t *cur = subtree; cur; cur = cur->next)
    708                         size += str_size(cur->name) + 1;
    709                
    710                 if (dry_run) {
    711                         ret.tag = SYSINFO_VAL_DATA;
    712                         ret.data.data = NULL;
    713                         ret.data.size = size;
    714                 } else {
    715                         /* Allocate buffer for subkeys */
    716                         char *names = (char *) malloc(size, FRAME_ATOMIC);
    717                         if (names == NULL)
    718                                 return ret;
    719                        
    720                         size_t pos = 0;
    721                         for (sysinfo_item_t *cur = subtree; cur; cur = cur->next) {
    722                                 str_cpy(names + pos, size - pos, cur->name);
    723                                 pos += str_size(cur->name) + 1;
    724                         }
    725                        
    726                         /* Correct return value */
    727                         ret.tag = SYSINFO_VAL_DATA;
    728                         ret.data.data = (void *) names;
    729                         ret.data.size = size;
    730                 }
    731         } else {
    732                 /* No item in the fixed sysinfo tree */
    733                 ret.tag = SYSINFO_VAL_UNDEFINED;
    734         }
    735        
    736         return ret;
    737 }
    738 
    739 /** Return sysinfo keys determined by name from user space
    740  *
    741  * The path string passed from the user space has to be properly
    742  * null-terminated (the last passed character must be null).
    743  *
    744  * @param ptr     Sysinfo path in the user address space.
    745  * @param size    Size of the path string.
    746  * @param dry_run Do not actually get any generated
    747  *                binary data, just calculate the size.
    748  *
    749  */
    750 NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
    751     bool dry_run)
    752 {
    753         sysinfo_return_t ret;
    754         ret.tag = SYSINFO_VAL_UNDEFINED;
    755        
    756         if (size > SYSINFO_MAX_PATH)
    757                 return ret;
    758        
    759         char *path = (char *) malloc(size + 1, 0);
    760         ASSERT(path);
    761        
    762         if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
    763             (path[size] == 0)) {
    764                 /*
    765                  * Prevent other functions from messing with sysinfo while we
    766                  * are reading it.
    767                  */
    768                 mutex_lock(&sysinfo_lock);
    769                 ret = sysinfo_get_keys(path, NULL, dry_run);
    770                 mutex_unlock(&sysinfo_lock);
    771         }
    772        
    773         free(path);
    774         return ret;
    775 }
    776 
    777 /** Get the sysinfo keys size (syscall)
    778  *
    779  * The path string passed from the user space has
    780  * to be properly null-terminated (the last passed
    781  * character must be null).
    782  *
    783  * @param path_ptr  Sysinfo path in the user address space.
    784  * @param path_size Size of the path string.
    785  * @param size_ptr  User space pointer where to store the
    786  *                  keys size.
    787  *
    788  * @return Error code (EOK in case of no error).
    789  *
    790  */
    791 sysarg_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
    792     void *size_ptr)
    793 {
    794         int rc;
    795        
    796         /*
    797          * Get the keys.
    798          *
    799          * N.B.: There is no need to free any potential keys
    800          * since we request a dry run.
    801          */
    802         sysinfo_return_t ret =
    803             sysinfo_get_keys_uspace(path_ptr, path_size, true);
    804        
    805         /* Check return data tag */
    806         if (ret.tag == SYSINFO_VAL_DATA)
    807                 rc = copy_to_uspace(size_ptr, &ret.data.size,
    808                     sizeof(ret.data.size));
    809         else
    810                 rc = EINVAL;
    811        
    812         return (sysarg_t) rc;
    813 }
    814 
    815 /** Get the sysinfo keys (syscall)
    816  *
    817  * The path string passed from the user space has
    818  * to be properly null-terminated (the last passed
    819  * character must be null).
    820  *
    821  * If the user space buffer size does not equal
    822  * the actual size of the returned data, the data
    823  * is truncated.
    824  *
    825  * The actual size of data returned is stored to
    826  * size_ptr.
    827  *
    828  * @param path_ptr    Sysinfo path in the user address space.
    829  * @param path_size   Size of the path string.
    830  * @param buffer_ptr  User space pointer to the buffer where
    831  *                    to store the binary data.
    832  * @param buffer_size User space buffer size.
    833  * @param size_ptr    User space pointer where to store the
    834  *                    binary data size.
    835  *
    836  * @return Error code (EOK in case of no error).
    837  *
    838  */
    839 sysarg_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
    840     void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
    841 {
    842         int rc;
    843        
    844         /* Get the keys */
    845         sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
    846             false);
    847        
    848         /* Check return data tag */
    849         if (ret.tag == SYSINFO_VAL_DATA) {
    850                 size_t size = min(ret.data.size, buffer_size);
    851                 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
    852                 if (rc == EOK)
    853                         rc = copy_to_uspace(size_ptr, &size, sizeof(size));
    854                
    855                 free(ret.data.data);
    856         } else
    857                 rc = EINVAL;
    858        
    859         return (sysarg_t) rc;
    860649}
    861650
     
    883672       
    884673        /*
    885          * Map generated value types to constant types (user space does
    886          * not care whether the value is constant or generated).
     674         * Map generated value types to constant types (user space does not care
     675         * whether the value is constant or generated).
    887676         */
    888677        if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
     
    912701{
    913702        int rc;
    914        
     703
    915704        /*
    916705         * Get the item.
    917706         *
    918          * N.B.: There is no need to free any potential generated binary
    919          * data since we request a dry run.
     707         * N.B.: There is no need to free any potential generated binary data
     708         * since we request a dry run.
    920709         */
    921710        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
     
    952741         * Get the item.
    953742         *
    954          * N.B.: There is no need to free any potential generated binary
    955          * data since we request a dry run.
     743         * N.B.: There is no need to free any potential generated binary data
     744         * since we request a dry run.
    956745         */
    957746        sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
Note: See TracChangeset for help on using the changeset viewer.