1 /* 2 * Copyright 2002-2007, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Thomas Kurschel. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 /** Manages kernel add-ons and their exported modules. */ 10 11 12 #include <boot_device.h> 13 #include <elf.h> 14 #include <kmodule.h> 15 #include <lock.h> 16 #include <vfs.h> 17 18 #include <boot/elf.h> 19 #include <fs/KPath.h> 20 #include <util/khash.h> 21 22 #include <errno.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <sys/stat.h> 26 27 28 //#define TRACE_MODULE 29 #ifdef TRACE_MODULE 30 # define TRACE(x) dprintf x 31 #else 32 # define TRACE(x) ; 33 #endif 34 #define FATAL(x) dprintf x 35 36 37 #define MODULE_HASH_SIZE 16 38 39 /** The modules referenced by this structure are built-in 40 * modules that can't be loaded from disk. 41 */ 42 43 extern module_info gDeviceManagerModule; 44 extern module_info gDeviceRootModule; 45 extern module_info gDeviceForDriversModule; 46 extern module_info gFrameBufferConsoleModule; 47 48 // file systems 49 extern module_info gRootFileSystem; 50 extern module_info gDeviceFileSystem; 51 extern module_info gPipeFileSystem; 52 53 static module_info *sBuiltInModules[] = { 54 &gDeviceManagerModule, 55 &gDeviceRootModule, 56 &gDeviceForDriversModule, 57 &gFrameBufferConsoleModule, 58 59 &gRootFileSystem, 60 &gDeviceFileSystem, 61 &gPipeFileSystem, 62 NULL 63 }; 64 65 enum module_state { 66 MODULE_QUERIED = 0, 67 MODULE_LOADED, 68 MODULE_INIT, 69 MODULE_READY, 70 MODULE_UNINIT, 71 MODULE_ERROR 72 }; 73 74 75 /* Each loaded module image (which can export several modules) is put 76 * in a hash (gModuleImagesHash) to be easily found when you search 77 * for a specific file name. 78 * ToDo: Could use only the inode number for hashing. Would probably be 79 * a little bit slower, but would lower the memory foot print quite a lot. 80 */ 81 82 struct module_image { 83 struct module_image *next; 84 module_info **info; /* the module_info we use */ 85 module_dependency *dependencies; 86 char *path; /* the full path for the module */ 87 image_id image; 88 int32 ref_count; /* how many ref's to this file */ 89 bool keep_loaded; 90 }; 91 92 /* Each known module will have this structure which is put in the 93 * gModulesHash, and looked up by name. 94 */ 95 96 struct module { 97 struct module *next; 98 ::module_image *module_image; 99 char *name; 100 char *file; 101 int32 ref_count; 102 module_info *info; /* will only be valid if ref_count > 0 */ 103 int32 offset; /* this is the offset in the headers */ 104 module_state state; /* state of module */ 105 uint32 flags; 106 }; 107 108 #define B_BUILT_IN_MODULE 2 109 110 typedef struct module_path { 111 const char *name; 112 uint32 base_length; 113 } module_path; 114 115 typedef struct module_iterator { 116 module_path *stack; 117 int32 stack_size; 118 int32 stack_current; 119 120 char *prefix; 121 size_t prefix_length; 122 DIR *current_dir; 123 status_t status; 124 int32 module_offset; 125 /* This is used to keep track of which module_info 126 * within a module we're addressing. */ 127 ::module_image *module_image; 128 module_info **current_header; 129 const char *current_path; 130 uint32 path_base_length; 131 const char *current_module_path; 132 bool builtin_modules; 133 bool loaded_modules; 134 } module_iterator; 135 136 137 static bool sDisableUserAddOns = false; 138 139 /* locking scheme: there is a global lock only; having several locks 140 * makes trouble if dependent modules get loaded concurrently -> 141 * they have to wait for each other, i.e. we need one lock per module; 142 * also we must detect circular references during init and not dead-lock 143 */ 144 static recursive_lock sModulesLock; 145 146 /* These are the standard base paths where we start to look for modules 147 * to load. Order is important, the last entry here will be searched 148 * first. 149 * ToDo: these should probably be retrieved by using find_directory(). 150 */ 151 static const char * const sModulePaths[] = { 152 "/boot/beos/system/add-ons/kernel", 153 "/boot/home/config/add-ons/kernel", 154 }; 155 156 #define NUM_MODULE_PATHS (sizeof(sModulePaths) / sizeof(sModulePaths[0])) 157 #define FIRST_USER_MODULE_PATH (NUM_MODULE_PATHS - 1) /* first user path */ 158 159 /* we store the loaded modules by directory path, and all known modules by module name 160 * in a hash table for quick access 161 */ 162 static hash_table *sModuleImagesHash; 163 static hash_table *sModulesHash; 164 165 166 /** calculates hash for a module using its name */ 167 168 static uint32 169 module_hash(void *_module, const void *_key, uint32 range) 170 { 171 module *module = (struct module *)_module; 172 const char *name = (const char *)_key; 173 174 if (module != NULL) 175 return hash_hash_string(module->name) % range; 176 177 if (name != NULL) 178 return hash_hash_string(name) % range; 179 180 return 0; 181 } 182 183 184 /** compares a module to a given name */ 185 186 static int 187 module_compare(void *_module, const void *_key) 188 { 189 module *module = (struct module *)_module; 190 const char *name = (const char *)_key; 191 if (name == NULL) 192 return -1; 193 194 return strcmp(module->name, name); 195 } 196 197 198 /** calculates the hash of a module image using its path */ 199 200 static uint32 201 module_image_hash(void *_module, const void *_key, uint32 range) 202 { 203 module_image *image = (module_image *)_module; 204 const char *path = (const char *)_key; 205 206 if (image != NULL) 207 return hash_hash_string(image->path) % range; 208 209 if (path != NULL) 210 return hash_hash_string(path) % range; 211 212 return 0; 213 } 214 215 216 /** compares a module image to a path */ 217 218 static int 219 module_image_compare(void *_module, const void *_key) 220 { 221 module_image *image = (module_image *)_module; 222 const char *path = (const char *)_key; 223 if (path == NULL) 224 return -1; 225 226 return strcmp(image->path, path); 227 } 228 229 230 static inline void 231 inc_module_ref_count(struct module *module) 232 { 233 module->ref_count++; 234 } 235 236 237 static inline void 238 dec_module_ref_count(struct module *module) 239 { 240 module->ref_count--; 241 } 242 243 244 /** Try to load the module image at the specified location. 245 * If it could be loaded, it returns B_OK, and stores a pointer 246 * to the module_image object in "_moduleImage". 247 */ 248 249 static status_t 250 load_module_image(const char *path, module_image **_moduleImage) 251 { 252 module_image *moduleImage; 253 status_t status; 254 image_id image; 255 256 TRACE(("load_module_image(path = \"%s\", _image = %p)\n", path, _moduleImage)); 257 ASSERT(_moduleImage != NULL); 258 259 image = load_kernel_add_on(path); 260 if (image < 0) { 261 dprintf("load_module_image(%s) failed: %s\n", path, strerror(image)); 262 return image; 263 } 264 265 moduleImage = (module_image *)malloc(sizeof(module_image)); 266 if (!moduleImage) { 267 status = B_NO_MEMORY; 268 goto err; 269 } 270 271 if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA, 272 (void **)&moduleImage->info) != B_OK) { 273 TRACE(("load_module_image: Failed to load \"%s\" due to lack of 'modules' symbol\n", path)); 274 status = B_BAD_TYPE; 275 goto err1; 276 } 277 278 moduleImage->dependencies = NULL; 279 get_image_symbol(image, "module_dependencies", B_SYMBOL_TYPE_DATA, 280 (void **)&moduleImage->dependencies); 281 // this is allowed to be NULL 282 283 moduleImage->path = strdup(path); 284 if (!moduleImage->path) { 285 status = B_NO_MEMORY; 286 goto err1; 287 } 288 289 moduleImage->image = image; 290 moduleImage->ref_count = 0; 291 moduleImage->keep_loaded = false; 292 293 recursive_lock_lock(&sModulesLock); 294 hash_insert(sModuleImagesHash, moduleImage); 295 recursive_lock_unlock(&sModulesLock); 296 297 *_moduleImage = moduleImage; 298 return B_OK; 299 300 err1: 301 free(moduleImage); 302 err: 303 unload_kernel_add_on(image); 304 305 return status; 306 } 307 308 309 static status_t 310 unload_module_image(module_image *moduleImage, const char *path) 311 { 312 TRACE(("unload_module_image(image = %p, path = %s)\n", moduleImage, path)); 313 314 recursive_lock_lock(&sModulesLock); 315 316 if (moduleImage == NULL) { 317 // if no image was specified, lookup it up in the hash table 318 moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path); 319 if (moduleImage == NULL) { 320 recursive_lock_unlock(&sModulesLock); 321 return B_ENTRY_NOT_FOUND; 322 } 323 } 324 325 if (moduleImage->ref_count != 0) { 326 FATAL(("Can't unload %s due to ref_cnt = %ld\n", moduleImage->path, moduleImage->ref_count)); 327 return B_ERROR; 328 } 329 330 hash_remove(sModuleImagesHash, moduleImage); 331 recursive_lock_unlock(&sModulesLock); 332 333 unload_kernel_add_on(moduleImage->image); 334 free(moduleImage->path); 335 free(moduleImage); 336 337 return B_OK; 338 } 339 340 341 static void 342 put_module_image(module_image *image) 343 { 344 int32 refCount = atomic_add(&image->ref_count, -1); 345 ASSERT(refCount > 0); 346 347 // Don't unload anything when there is no boot device yet 348 // (because chances are that we will never be able to access it again) 349 350 if (refCount == 1 && !image->keep_loaded && gBootDevice > 0) 351 unload_module_image(image, NULL); 352 } 353 354 355 static status_t 356 get_module_image(const char *path, module_image **_image) 357 { 358 struct module_image *image; 359 360 TRACE(("get_module_image(path = \"%s\", _image = %p)\n", path, _image)); 361 362 recursive_lock_lock(&sModulesLock); 363 364 image = (module_image *)hash_lookup(sModuleImagesHash, path); 365 if (image == NULL) { 366 status_t status = load_module_image(path, &image); 367 if (status < B_OK) { 368 recursive_lock_unlock(&sModulesLock); 369 return status; 370 } 371 } 372 373 atomic_add(&image->ref_count, 1); 374 *_image = image; 375 376 recursive_lock_unlock(&sModulesLock); 377 378 return B_OK; 379 } 380 381 382 /** Extract the information from the module_info structure pointed at 383 * by "info" and create the entries required for access to it's details. 384 */ 385 386 static status_t 387 create_module(module_info *info, const char *file, int offset, module **_module) 388 { 389 module *module; 390 391 TRACE(("create_module(info = %p, file = \"%s\", offset = %d, _module = %p)\n", 392 info, file, offset, _module)); 393 394 if (!info->name) 395 return B_BAD_VALUE; 396 397 module = (struct module *)hash_lookup(sModulesHash, info->name); 398 if (module) { 399 FATAL(("Duplicate module name (%s) detected... ignoring new one\n", info->name)); 400 return B_FILE_EXISTS; 401 } 402 403 if ((module = (struct module *)malloc(sizeof(struct module))) == NULL) 404 return B_NO_MEMORY; 405 406 TRACE(("create_module: name = \"%s\", file = \"%s\"\n", info->name, file)); 407 408 module->module_image = NULL; 409 module->name = strdup(info->name); 410 if (module->name == NULL) { 411 free(module); 412 return B_NO_MEMORY; 413 } 414 415 module->file = strdup(file); 416 if (module->file == NULL) { 417 free(module->name); 418 free(module); 419 return B_NO_MEMORY; 420 } 421 422 module->state = MODULE_QUERIED; 423 module->info = info; 424 module->offset = offset; 425 // record where the module_info can be found in the module_info array 426 module->ref_count = 0; 427 module->flags = info->flags; 428 429 recursive_lock_lock(&sModulesLock); 430 hash_insert(sModulesHash, module); 431 recursive_lock_unlock(&sModulesLock); 432 433 if (_module) 434 *_module = module; 435 436 return B_OK; 437 } 438 439 440 /** Loads the file at "path" and scans all modules contained therein. 441 * Returns B_OK if "searchedName" could be found under those modules, 442 * B_ENTRY_NOT_FOUND if not. 443 * Must only be called for files that haven't been scanned yet. 444 * "searchedName" is allowed to be NULL (if all modules should be scanned) 445 */ 446 447 static status_t 448 check_module_image(const char *path, const char *searchedName) 449 { 450 module_image *image; 451 module_info **info; 452 int index = 0, match = B_ENTRY_NOT_FOUND; 453 454 TRACE(("check_module_image(path = \"%s\", searchedName = \"%s\")\n", path, searchedName)); 455 456 if (get_module_image(path, &image) < B_OK) 457 return B_ENTRY_NOT_FOUND; 458 459 for (info = image->info; *info; info++) { 460 // try to create a module for every module_info, check if the 461 // name matches if it was a new entry 462 if (create_module(*info, path, index++, NULL) == B_OK) { 463 if (searchedName && !strcmp((*info)->name, searchedName)) 464 match = B_OK; 465 } 466 } 467 468 // The module we looked for couldn't be found, so we can unload the 469 // loaded module at this point 470 if (match != B_OK) { 471 TRACE(("check_module_file: unloading module file \"%s\" (not used yet)\n", path)); 472 unload_module_image(image, path); 473 } 474 475 // decrement the ref we got in get_module_image 476 put_module_image(image); 477 478 return match; 479 } 480 481 482 /** This is only called if we fail to find a module already in our cache... 483 * saves us some extra checking here :) 484 */ 485 486 static module * 487 search_module(const char *name) 488 { 489 status_t status = B_ENTRY_NOT_FOUND; 490 uint32 i; 491 492 TRACE(("search_module(%s)\n", name)); 493 494 for (i = 0; i < NUM_MODULE_PATHS; i++) { 495 char path[B_FILE_NAME_LENGTH]; 496 497 if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH) 498 return NULL; 499 500 // let the VFS find that module for us 501 502 status = vfs_get_module_path(sModulePaths[i], name, path, sizeof(path)); 503 if (status == B_OK) { 504 status = check_module_image(path, name); 505 if (status == B_OK) 506 break; 507 } 508 } 509 510 if (status != B_OK) 511 return NULL; 512 513 return (module *)hash_lookup(sModulesHash, name); 514 } 515 516 517 static status_t 518 put_dependent_modules(struct module *module) 519 { 520 module_dependency *dependencies; 521 int32 i = 0; 522 523 if (module->module_image == NULL 524 || (dependencies = module->module_image->dependencies) == NULL) 525 return B_OK; 526 527 for (; dependencies[i].name != NULL; i++) { 528 status_t status = put_module(dependencies[i].name); 529 if (status < B_OK) 530 return status; 531 } 532 533 return B_OK; 534 } 535 536 537 static status_t 538 get_dependent_modules(struct module *module) 539 { 540 module_dependency *dependencies; 541 int32 i = 0; 542 543 // built-in modules don't have a module_image structure 544 if (module->module_image == NULL 545 || (dependencies = module->module_image->dependencies) == NULL) 546 return B_OK; 547 548 TRACE(("resolving module dependencies...\n")); 549 550 for (; dependencies[i].name != NULL; i++) { 551 status_t status = get_module(dependencies[i].name, dependencies[i].info); 552 if (status < B_OK) { 553 TRACE(("loading dependent module \"%s\" failed!\n", dependencies[i].name)); 554 return status; 555 } 556 } 557 558 return B_OK; 559 } 560 561 562 /** Initializes a loaded module depending on its state */ 563 564 static inline status_t 565 init_module(module *module) 566 { 567 switch (module->state) { 568 case MODULE_QUERIED: 569 case MODULE_LOADED: 570 { 571 status_t status; 572 module->state = MODULE_INIT; 573 574 // resolve dependencies 575 576 status = get_dependent_modules(module); 577 if (status < B_OK) { 578 module->state = MODULE_LOADED; 579 return status; 580 } 581 582 // init module 583 584 TRACE(("initializing module %s (at %p)... \n", module->name, module->info->std_ops)); 585 status = module->info->std_ops(B_MODULE_INIT); 586 TRACE(("...done (%s)\n", strerror(status))); 587 588 if (status >= B_OK) 589 module->state = MODULE_READY; 590 else { 591 put_dependent_modules(module); 592 module->state = MODULE_LOADED; 593 } 594 595 return status; 596 } 597 598 case MODULE_READY: 599 return B_OK; 600 601 case MODULE_INIT: 602 FATAL(("circular reference to %s\n", module->name)); 603 return B_ERROR; 604 605 case MODULE_UNINIT: 606 FATAL(("tried to load module %s which is currently unloading\n", module->name)); 607 return B_ERROR; 608 609 case MODULE_ERROR: 610 FATAL(("cannot load module %s because its earlier unloading failed\n", module->name)); 611 return B_ERROR; 612 613 default: 614 return B_ERROR; 615 } 616 // never trespasses here 617 } 618 619 620 /** Uninitializes a module depeding on its state */ 621 622 static inline int 623 uninit_module(module *module) 624 { 625 TRACE(("uninit_module(%s)\n", module->name)); 626 627 switch (module->state) { 628 case MODULE_QUERIED: 629 case MODULE_LOADED: 630 return B_NO_ERROR; 631 632 case MODULE_INIT: 633 panic("Trying to unload module %s which is initializing\n", module->name); 634 return B_ERROR; 635 636 case MODULE_UNINIT: 637 panic("Trying to unload module %s which is un-initializing\n", module->name); 638 return B_ERROR; 639 640 case MODULE_READY: 641 { 642 status_t status; 643 644 module->state = MODULE_UNINIT; 645 646 TRACE(("uninitializing module %s...\n", module->name)); 647 status = module->info->std_ops(B_MODULE_UNINIT); 648 TRACE(("...done (%s)\n", strerror(status))); 649 650 if (status == B_NO_ERROR) { 651 module->state = MODULE_LOADED; 652 653 put_dependent_modules(module); 654 return 0; 655 } 656 657 FATAL(("Error unloading module %s (%s)\n", module->name, strerror(status))); 658 659 module->state = MODULE_ERROR; 660 module->flags |= B_KEEP_LOADED; 661 662 return status; 663 } 664 default: 665 return B_ERROR; 666 } 667 // never trespasses here 668 } 669 670 671 static const char * 672 iterator_pop_path_from_stack(module_iterator *iterator, uint32 *_baseLength) 673 { 674 if (iterator->stack_current <= 0) 675 return NULL; 676 677 if (_baseLength) 678 *_baseLength = iterator->stack[iterator->stack_current - 1].base_length; 679 680 return iterator->stack[--iterator->stack_current].name; 681 } 682 683 684 static status_t 685 iterator_push_path_on_stack(module_iterator *iterator, const char *path, uint32 baseLength) 686 { 687 if (iterator->stack_current + 1 > iterator->stack_size) { 688 // allocate new space on the stack 689 module_path *stack = (module_path *)realloc(iterator->stack, 690 (iterator->stack_size + 8) * sizeof(module_path)); 691 if (stack == NULL) 692 return B_NO_MEMORY; 693 694 iterator->stack = stack; 695 iterator->stack_size += 8; 696 } 697 698 iterator->stack[iterator->stack_current].name = path; 699 iterator->stack[iterator->stack_current++].base_length = baseLength; 700 return B_OK; 701 } 702 703 704 static status_t 705 iterator_get_next_module(module_iterator *iterator, char *buffer, 706 size_t *_bufferSize) 707 { 708 status_t status; 709 710 TRACE(("iterator_get_next_module() -- start\n")); 711 712 if (iterator->builtin_modules) { 713 for (int32 i = iterator->module_offset; sBuiltInModules[i] != NULL; i++) { 714 // the module name must fit the prefix 715 if (strncmp(sBuiltInModules[i]->name, iterator->prefix, 716 iterator->prefix_length)) 717 continue; 718 719 *_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name, 720 *_bufferSize); 721 iterator->module_offset = i + 1; 722 return B_OK; 723 } 724 iterator->builtin_modules = false; 725 } 726 727 if (iterator->loaded_modules) { 728 recursive_lock_lock(&sModulesLock); 729 hash_iterator hashIterator; 730 hash_open(sModulesHash, &hashIterator); 731 732 struct module *module = (struct module *)hash_next(sModulesHash, 733 &hashIterator); 734 for (int32 i = 0; module != NULL; i++) { 735 if (i >= iterator->module_offset) { 736 if (!strncmp(module->name, iterator->prefix, 737 iterator->prefix_length)) { 738 *_bufferSize = strlcpy(buffer, module->name, *_bufferSize); 739 iterator->module_offset = i + 1; 740 741 hash_close(sModulesHash, &hashIterator, false); 742 recursive_lock_unlock(&sModulesLock); 743 return B_OK; 744 } 745 } 746 module = (struct module *)hash_next(sModulesHash, &hashIterator); 747 } 748 749 hash_close(sModulesHash, &hashIterator, false); 750 recursive_lock_unlock(&sModulesLock); 751 752 // prevent from falling into modules hash iteration again 753 iterator->loaded_modules = false; 754 } 755 756 nextPath: 757 if (iterator->current_dir == NULL) { 758 // get next directory path from the stack 759 const char *path = iterator_pop_path_from_stack(iterator, 760 &iterator->path_base_length); 761 if (path == NULL) { 762 // we are finished, there are no more entries on the stack 763 return B_ENTRY_NOT_FOUND; 764 } 765 766 free((void *)iterator->current_path); 767 iterator->current_path = path; 768 iterator->current_dir = opendir(path); 769 TRACE(("open directory at %s -> %p\n", path, iterator->current_dir)); 770 771 if (iterator->current_dir == NULL) { 772 // we don't throw an error here, but silently go to 773 // the next directory on the stack 774 goto nextPath; 775 } 776 } 777 778 nextModuleImage: 779 if (iterator->current_header == NULL) { 780 // get next entry from the current directory 781 782 errno = 0; 783 784 struct dirent *dirent; 785 if ((dirent = readdir(iterator->current_dir)) == NULL) { 786 closedir(iterator->current_dir); 787 iterator->current_dir = NULL; 788 789 if (errno < B_OK) 790 return errno; 791 792 goto nextPath; 793 } 794 795 // check if the prefix matches 796 int32 passedOffset, commonLength; 797 passedOffset = strlen(iterator->current_path) + 1; 798 commonLength = iterator->path_base_length + iterator->prefix_length 799 - passedOffset; 800 801 if (commonLength > 0) { 802 // the prefix still reaches into the new path part 803 int32 length = strlen(dirent->d_name); 804 if (commonLength > length) 805 commonLength = length; 806 807 if (strncmp(dirent->d_name, iterator->prefix + passedOffset 808 - iterator->path_base_length, commonLength)) 809 goto nextModuleImage; 810 } 811 812 // we're not interested in traversing these again 813 if (!strcmp(dirent->d_name, ".") 814 || !strcmp(dirent->d_name, "..")) 815 goto nextModuleImage; 816 817 // build absolute path to current file 818 KPath path(iterator->current_path); 819 if (path.InitCheck() != B_OK) 820 return B_NO_MEMORY; 821 822 if (path.Append(dirent->d_name) != B_OK) 823 return B_BUFFER_OVERFLOW; 824 825 // find out if it's a directory or a file 826 struct stat st; 827 if (stat(path.Path(), &st) < 0) 828 return errno; 829 830 iterator->current_module_path = strdup(path.Path()); 831 if (iterator->current_module_path == NULL) 832 return B_NO_MEMORY; 833 834 if (S_ISDIR(st.st_mode)) { 835 status = iterator_push_path_on_stack(iterator, 836 iterator->current_module_path, iterator->path_base_length); 837 if (status < B_OK) 838 return status; 839 840 iterator->current_module_path = NULL; 841 goto nextModuleImage; 842 } 843 844 if (!S_ISREG(st.st_mode)) 845 return B_BAD_TYPE; 846 847 TRACE(("open module at %s\n", path.Path())); 848 849 status = get_module_image(path.Path(), &iterator->module_image); 850 if (status < B_OK) { 851 free((void *)iterator->current_module_path); 852 iterator->current_module_path = NULL; 853 goto nextModuleImage; 854 } 855 856 iterator->current_header = iterator->module_image->info; 857 iterator->module_offset = 0; 858 } 859 860 // search the current module image until we've got a match 861 while (*iterator->current_header != NULL) { 862 module_info *info = *iterator->current_header; 863 864 // ToDo: we might want to create a module here and cache it in the hash table 865 866 iterator->current_header++; 867 iterator->module_offset++; 868 869 if (strncmp(info->name, iterator->prefix, iterator->prefix_length)) 870 continue; 871 872 *_bufferSize = strlcpy(buffer, info->name, *_bufferSize); 873 return B_OK; 874 } 875 876 // leave this module and get the next one 877 878 iterator->current_header = NULL; 879 free((void *)iterator->current_module_path); 880 iterator->current_module_path = NULL; 881 882 put_module_image(iterator->module_image); 883 iterator->module_image = NULL; 884 885 goto nextModuleImage; 886 } 887 888 889 static void 890 register_builtin_modules(struct module_info **info) 891 { 892 for (; *info; info++) { 893 (*info)->flags |= B_BUILT_IN_MODULE; 894 // this is an internal flag, it doesn't have to be set by modules itself 895 896 if (create_module(*info, "", -1, NULL) != B_OK) 897 dprintf("creation of built-in module \"%s\" failed!\n", (*info)->name); 898 } 899 } 900 901 902 static status_t 903 register_preloaded_module_image(struct preloaded_image *image) 904 { 905 module_image *moduleImage; 906 struct module_info **info; 907 status_t status; 908 int32 index = 0; 909 910 TRACE(("register_preloaded_module_image(image = \"%s\")\n", image->name)); 911 912 if (image->id < 0) 913 return B_BAD_VALUE; 914 915 moduleImage = (module_image *)malloc(sizeof(module_image)); 916 if (moduleImage == NULL) 917 return B_NO_MEMORY; 918 919 if (get_image_symbol(image->id, "modules", B_SYMBOL_TYPE_DATA, 920 (void **)&moduleImage->info) != B_OK) { 921 status = B_BAD_TYPE; 922 goto error; 923 } 924 925 moduleImage->dependencies = NULL; 926 get_image_symbol(image->id, "module_dependencies", B_SYMBOL_TYPE_DATA, 927 (void **)&moduleImage->dependencies); 928 // this is allowed to be NULL 929 930 // Try to recreate the full module path, so that we don't try to load the 931 // image again when asked for a module it does not export (would only be 932 // problematic if it had got replaced and the new file actually exports 933 // that module). Also helpful for recurse_directory(). 934 { 935 // ToDo: this is kind of a hack to have the full path in the hash 936 // (it always assumes the preloaded add-ons to be in the system directory) 937 char path[B_FILE_NAME_LENGTH]; 938 const char *name, *suffix; 939 if (moduleImage->info[0] 940 && (suffix = strstr(name = moduleImage->info[0]->name, image->name)) != NULL) { 941 // even if strlcpy() is used here, it's by no means safe against buffer overflows 942 size_t length = strlcpy(path, "/boot/beos/system/add-ons/kernel/", sizeof(path)); 943 strlcpy(path + length, name, strlen(image->name) + 1 + (suffix - name)); 944 945 moduleImage->path = strdup(path); 946 } else 947 moduleImage->path = strdup(image->name); 948 } 949 if (moduleImage->path == NULL) { 950 status = B_NO_MEMORY; 951 goto error; 952 } 953 954 moduleImage->image = image->id; 955 moduleImage->ref_count = 0; 956 moduleImage->keep_loaded = false; 957 958 hash_insert(sModuleImagesHash, moduleImage); 959 960 for (info = moduleImage->info; *info; info++) { 961 create_module(*info, moduleImage->path, index++, NULL); 962 } 963 964 return B_OK; 965 966 error: 967 free(moduleImage); 968 969 // we don't need this image anymore 970 unload_kernel_add_on(image->id); 971 972 return status; 973 } 974 975 976 static int 977 dump_modules(int argc, char **argv) 978 { 979 hash_iterator iterator; 980 struct module_image *image; 981 struct module *module; 982 983 hash_rewind(sModulesHash, &iterator); 984 dprintf("-- known modules:\n"); 985 986 while ((module = (struct module *)hash_next(sModulesHash, &iterator)) != NULL) { 987 dprintf("%p: \"%s\", \"%s\" (%ld), refcount = %ld, state = %d, mimage = %p\n", 988 module, module->name, module->file, module->offset, module->ref_count, 989 module->state, module->module_image); 990 } 991 992 hash_rewind(sModuleImagesHash, &iterator); 993 dprintf("\n-- loaded module images:\n"); 994 995 while ((image = (struct module_image *)hash_next(sModuleImagesHash, &iterator)) != NULL) { 996 dprintf("%p: \"%s\" (image_id = %ld), info = %p, refcount = %ld, %s\n", image, 997 image->path, image->image, image->info, image->ref_count, 998 image->keep_loaded ? "keep loaded" : "can be unloaded"); 999 } 1000 return 0; 1001 } 1002 1003 1004 // #pragma mark - 1005 // Exported Kernel API (private part) 1006 1007 1008 /** Unloads a module in case it's not in use. This is the counterpart 1009 * to load_module(). 1010 */ 1011 1012 status_t 1013 unload_module(const char *path) 1014 { 1015 struct module_image *moduleImage; 1016 1017 recursive_lock_lock(&sModulesLock); 1018 moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path); 1019 recursive_lock_unlock(&sModulesLock); 1020 1021 if (moduleImage == NULL) 1022 return B_ENTRY_NOT_FOUND; 1023 1024 put_module_image(moduleImage); 1025 return B_OK; 1026 } 1027 1028 1029 /** Unlike get_module(), this function lets you specify the add-on to 1030 * be loaded by path. 1031 * However, you must not use the exported modules without having called 1032 * get_module() on them. When you're done with the NULL terminated 1033 * \a modules array, you have to call unload_module(), no matter if 1034 * you're actually using any of the modules or not - of course, the 1035 * add-on won't be unloaded until the last put_module(). 1036 */ 1037 1038 status_t 1039 load_module(const char *path, module_info ***_modules) 1040 { 1041 module_image *moduleImage; 1042 status_t status = get_module_image(path, &moduleImage); 1043 if (status != B_OK) 1044 return status; 1045 1046 *_modules = moduleImage->info; 1047 return B_OK; 1048 } 1049 1050 1051 /** Setup the module structures and data for use - must be called 1052 * before any other module call. 1053 */ 1054 1055 status_t 1056 module_init(kernel_args *args) 1057 { 1058 struct preloaded_image *image; 1059 1060 if (recursive_lock_init(&sModulesLock, "modules rlock") < B_OK) 1061 return B_ERROR; 1062 1063 sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash); 1064 if (sModulesHash == NULL) 1065 return B_NO_MEMORY; 1066 1067 sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare, module_image_hash); 1068 if (sModuleImagesHash == NULL) 1069 return B_NO_MEMORY; 1070 1071 // register built-in modules 1072 1073 register_builtin_modules(sBuiltInModules); 1074 1075 // register preloaded images 1076 1077 for (image = args->preloaded_images; image != NULL; image = image->next) { 1078 status_t status = register_preloaded_module_image(image); 1079 if (status != B_OK) 1080 dprintf("Could not register image \"%s\": %s\n", image->name, strerror(status)); 1081 } 1082 1083 // ToDo: set sDisableUserAddOns from kernel_args! 1084 1085 add_debugger_command("modules", &dump_modules, "list all known & loaded modules"); 1086 1087 return B_OK; 1088 } 1089 1090 1091 // #pragma mark - 1092 // Exported Kernel API (public part) 1093 1094 1095 /** This returns a pointer to a structure that can be used to 1096 * iterate through a list of all modules available under 1097 * a given prefix. 1098 * All paths will be searched and the returned list will 1099 * contain all modules available under the prefix. 1100 * The structure is then used by read_next_module_name(), and 1101 * must be freed by calling close_module_list(). 1102 */ 1103 1104 void * 1105 open_module_list(const char *prefix) 1106 { 1107 module_iterator *iterator; 1108 uint32 i; 1109 1110 TRACE(("open_module_list(prefix = %s)\n", prefix)); 1111 1112 if (sModulesHash == NULL) { 1113 dprintf("open_module_list() called too early!\n"); 1114 return NULL; 1115 } 1116 1117 iterator = (module_iterator *)malloc(sizeof(module_iterator)); 1118 if (!iterator) 1119 return NULL; 1120 1121 memset(iterator, 0, sizeof(module_iterator)); 1122 1123 iterator->prefix = strdup(prefix != NULL ? prefix : ""); 1124 if (iterator->prefix == NULL) { 1125 free(iterator); 1126 return NULL; 1127 } 1128 iterator->prefix_length = strlen(iterator->prefix); 1129 1130 if (gBootDevice > 0) { 1131 // We do have a boot device to scan 1132 1133 // first, we'll traverse over the built-in modules 1134 iterator->builtin_modules = true; 1135 iterator->loaded_modules = false; 1136 1137 // put all search paths on the stack 1138 for (i = 0; i < NUM_MODULE_PATHS; i++) { 1139 if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH) 1140 break; 1141 1142 // Build path component: base path + '/' + prefix 1143 size_t length = strlen(sModulePaths[i]); 1144 char *path = (char *)malloc(length + iterator->prefix_length + 2); 1145 if (path == NULL) { 1146 // ToDo: should we abort the whole operation here? 1147 // if we do, don't forget to empty the stack 1148 continue; 1149 } 1150 1151 memcpy(path, sModulePaths[i], length); 1152 path[length] = '/'; 1153 memcpy(path + length + 1, iterator->prefix, 1154 iterator->prefix_length + 1); 1155 1156 iterator_push_path_on_stack(iterator, path, length + 1); 1157 } 1158 } else { 1159 // include loaded modules in case there is no boot device yet 1160 iterator->builtin_modules = false; 1161 iterator->loaded_modules = true; 1162 } 1163 1164 return (void *)iterator; 1165 } 1166 1167 1168 /** Frees the cookie allocated by open_module_list() 1169 */ 1170 1171 status_t 1172 close_module_list(void *cookie) 1173 { 1174 module_iterator *iterator = (module_iterator *)cookie; 1175 const char *path; 1176 1177 TRACE(("close_module_list()\n")); 1178 1179 if (iterator == NULL) 1180 return B_BAD_VALUE; 1181 1182 // free stack 1183 while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL) 1184 free((void *)path); 1185 1186 // close what have been left open 1187 if (iterator->module_image != NULL) 1188 put_module_image(iterator->module_image); 1189 1190 if (iterator->current_dir != NULL) 1191 closedir(iterator->current_dir); 1192 1193 free(iterator->stack); 1194 free((void *)iterator->current_path); 1195 free((void *)iterator->current_module_path); 1196 1197 free(iterator->prefix); 1198 free(iterator); 1199 1200 return 0; 1201 } 1202 1203 1204 /** Return the next module name from the available list, using 1205 * a structure previously created by a call to open_module_list(). 1206 * Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND 1207 * when done. 1208 */ 1209 1210 status_t 1211 read_next_module_name(void *cookie, char *buffer, size_t *_bufferSize) 1212 { 1213 module_iterator *iterator = (module_iterator *)cookie; 1214 status_t status; 1215 1216 TRACE(("read_next_module_name: looking for next module\n")); 1217 1218 if (iterator == NULL || buffer == NULL || _bufferSize == NULL) 1219 return B_BAD_VALUE; 1220 1221 if (iterator->status < B_OK) 1222 return iterator->status; 1223 1224 status = iterator->status; 1225 recursive_lock_lock(&sModulesLock); 1226 1227 status = iterator_get_next_module(iterator, buffer, _bufferSize); 1228 1229 iterator->status = status; 1230 recursive_lock_unlock(&sModulesLock); 1231 1232 TRACE(("read_next_module_name: finished with status %s\n", strerror(status))); 1233 return status; 1234 } 1235 1236 1237 /** Iterates through all loaded modules, and stores its path in "buffer". 1238 * ToDo: check if the function in BeOS really does that (could also mean: 1239 * iterate through all modules that are currently loaded; have a valid 1240 * module_image pointer, which would be hard to test for) 1241 */ 1242 1243 status_t 1244 get_next_loaded_module_name(uint32 *_cookie, char *buffer, size_t *_bufferSize) 1245 { 1246 if (sModulesHash == NULL) { 1247 dprintf("get_next_loaded_module_name() called too early!\n"); 1248 return NULL; 1249 } 1250 1251 //TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer)); 1252 1253 if (_cookie == NULL || buffer == NULL || _bufferSize == NULL) 1254 return B_BAD_VALUE; 1255 1256 status_t status = B_ENTRY_NOT_FOUND; 1257 uint32 offset = *_cookie; 1258 1259 recursive_lock_lock(&sModulesLock); 1260 1261 hash_iterator iterator; 1262 hash_open(sModulesHash, &iterator); 1263 struct module *module = (struct module *)hash_next(sModulesHash, 1264 &iterator); 1265 1266 for (uint32 i = 0; module != NULL; i++) { 1267 if (i >= offset) { 1268 *_bufferSize = strlcpy(buffer, module->name, *_bufferSize); 1269 *_cookie = i + 1; 1270 status = B_OK; 1271 break; 1272 } 1273 module = (struct module *)hash_next(sModulesHash, &iterator); 1274 } 1275 1276 hash_close(sModulesHash, &iterator, false); 1277 recursive_lock_unlock(&sModulesLock); 1278 1279 return status; 1280 } 1281 1282 1283 status_t 1284 get_module(const char *path, module_info **_info) 1285 { 1286 module_image *moduleImage; 1287 module *module; 1288 status_t status; 1289 1290 TRACE(("get_module(%s)\n", path)); 1291 1292 if (path == NULL) 1293 return B_BAD_VALUE; 1294 1295 recursive_lock_lock(&sModulesLock); 1296 1297 module = (struct module *)hash_lookup(sModulesHash, path); 1298 1299 // if we don't have it cached yet, search for it 1300 if (module == NULL) { 1301 module = search_module(path); 1302 if (module == NULL) { 1303 FATAL(("module: Search for %s failed.\n", path)); 1304 goto err; 1305 } 1306 } 1307 1308 if ((module->flags & B_BUILT_IN_MODULE) == 0) { 1309 /* We now need to find the module_image for the module. This should 1310 * be in memory if we have just run search_module(), but may not be 1311 * if we are using cached information. 1312 * We can't use the module->module_image pointer, because it is not 1313 * reliable at this point (it won't be set to NULL when the module_image 1314 * is unloaded). 1315 */ 1316 if (get_module_image(module->file, &moduleImage) < B_OK) 1317 goto err; 1318 1319 // (re)set in-memory data for the loaded module 1320 module->info = moduleImage->info[module->offset]; 1321 module->module_image = moduleImage; 1322 1323 // the module image must not be unloaded anymore 1324 if (module->flags & B_KEEP_LOADED) 1325 module->module_image->keep_loaded = true; 1326 } 1327 1328 // The state will be adjusted by the call to init_module 1329 // if we have just loaded the file 1330 if (module->ref_count == 0) 1331 status = init_module(module); 1332 else 1333 status = B_OK; 1334 1335 if (status == B_OK) { 1336 inc_module_ref_count(module); 1337 *_info = module->info; 1338 } else if ((module->flags & B_BUILT_IN_MODULE) == 0) 1339 put_module_image(module->module_image); 1340 1341 recursive_lock_unlock(&sModulesLock); 1342 return status; 1343 1344 err: 1345 recursive_lock_unlock(&sModulesLock); 1346 return B_ENTRY_NOT_FOUND; 1347 } 1348 1349 1350 status_t 1351 put_module(const char *path) 1352 { 1353 module *module; 1354 1355 TRACE(("put_module(path = %s)\n", path)); 1356 1357 recursive_lock_lock(&sModulesLock); 1358 1359 module = (struct module *)hash_lookup(sModulesHash, path); 1360 if (module == NULL) { 1361 FATAL(("module: We don't seem to have a reference to module %s\n", path)); 1362 recursive_lock_unlock(&sModulesLock); 1363 return B_BAD_VALUE; 1364 } 1365 1366 if ((module->flags & B_KEEP_LOADED) == 0) { 1367 dec_module_ref_count(module); 1368 1369 if (module->ref_count == 0) 1370 uninit_module(module); 1371 } 1372 1373 if ((module->flags & B_BUILT_IN_MODULE) == 0) 1374 put_module_image(module->module_image); 1375 1376 recursive_lock_unlock(&sModulesLock); 1377 return B_OK; 1378 } 1379