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