Changes in kernel/generic/src/sysinfo/sysinfo.c [e1b6742:137691a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/sysinfo/sysinfo.c
re1b6742 r137691a 37 37 #include <print.h> 38 38 #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 204845 39 46 40 bool 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])) 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])) 135 54 i++; 136 55 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 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; 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)); 157 125 } 126 127 //if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */ 128 // return NULL; 129 130 return NULL; 158 131 } 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."); 165 165 return NULL; 166 166 } 167 167 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 168 void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val) 169 { 304 170 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 */ 307 175 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; 309 179 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 183 void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn) 184 { 337 185 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 */ 340 190 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 199 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root) 200 { 366 201 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 */ 369 206 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 429 208 if (item != NULL) 430 209 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 213 void 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) { 504 231 case SYSINFO_VAL_UNDEFINED: 505 printf("+ %s\n", cur->name); 232 val = 0; 233 vtype = "UND"; 506 234 break; 507 235 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"; 510 238 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"; 619 242 break; 620 243 } 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 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; 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 } 629 279 return ret; 630 280 } 631 281 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 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; 837 316 } 838 317
Note:
See TracChangeset
for help on using the changeset viewer.