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