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