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