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