xref: /haiku/src/system/kernel/module.cpp (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
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 gDeviceForDriversModule;
49 extern module_info gFrameBufferConsoleModule;
50 
51 // file systems
52 extern module_info gRootFileSystem;
53 extern module_info gDeviceFileSystem;
54 
55 static module_info *sBuiltInModules[] = {
56 	&gDeviceManagerModule,
57 	&gDeviceRootModule,
58 	&gDeviceForDriversModule,
59 	&gFrameBufferConsoleModule,
60 
61 	&gRootFileSystem,
62 	&gDeviceFileSystem,
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  */
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 			status = module->info->std_ops(B_MODULE_INIT);
574 			TRACE(("...done (%s)\n", strerror(status)));
575 
576 			if (status >= B_OK)
577 				module->state = MODULE_READY;
578 			else {
579 				put_dependent_modules(module);
580 				module->state = MODULE_LOADED;
581 			}
582 
583 			return status;
584 		}
585 
586 		case MODULE_READY:
587 			return B_OK;
588 
589 		case MODULE_INIT:
590 			FATAL(("circular reference to %s\n", module->name));
591 			return B_ERROR;
592 
593 		case MODULE_UNINIT:
594 			FATAL(("tried to load module %s which is currently unloading\n", module->name));
595 			return B_ERROR;
596 
597 		case MODULE_ERROR:
598 			FATAL(("cannot load module %s because its earlier unloading failed\n", module->name));
599 			return B_ERROR;
600 
601 		default:
602 			return B_ERROR;
603 	}
604 	// never trespasses here
605 }
606 
607 
608 /*!	Uninitializes a module depeding on its state */
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 - Exported Kernel API (private part)
1003 
1004 
1005 /*!	Unloads a module in case it's not in use. This is the counterpart
1006 	to load_module().
1007 */
1008 status_t
1009 unload_module(const char *path)
1010 {
1011 	struct module_image *moduleImage;
1012 
1013 	recursive_lock_lock(&sModulesLock);
1014 	moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
1015 	recursive_lock_unlock(&sModulesLock);
1016 
1017 	if (moduleImage == NULL)
1018 		return B_ENTRY_NOT_FOUND;
1019 
1020 	put_module_image(moduleImage);
1021 	return B_OK;
1022 }
1023 
1024 
1025 /*!	Unlike get_module(), this function lets you specify the add-on to
1026 	be loaded by path.
1027 	However, you must not use the exported modules without having called
1028 	get_module() on them. When you're done with the NULL terminated
1029 	\a modules array, you have to call unload_module(), no matter if
1030 	you're actually using any of the modules or not - of course, the
1031 	add-on won't be unloaded until the last put_module().
1032 */
1033 status_t
1034 load_module(const char *path, module_info ***_modules)
1035 {
1036 	module_image *moduleImage;
1037 	status_t status = get_module_image(path, &moduleImage);
1038 	if (status != B_OK)
1039 		return status;
1040 
1041 	*_modules = moduleImage->info;
1042 	return B_OK;
1043 }
1044 
1045 
1046 /*! Setup the module structures and data for use - must be called
1047 	before any other module call.
1048 */
1049 status_t
1050 module_init(kernel_args *args)
1051 {
1052 	struct preloaded_image *image;
1053 
1054 	if (recursive_lock_init(&sModulesLock, "modules rlock") < B_OK)
1055 		return B_ERROR;
1056 
1057 	sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash);
1058 	if (sModulesHash == NULL)
1059 		return B_NO_MEMORY;
1060 
1061 	sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare,
1062 		module_image_hash);
1063 	if (sModuleImagesHash == NULL)
1064 		return B_NO_MEMORY;
1065 
1066 	// register built-in modules
1067 
1068 	register_builtin_modules(sBuiltInModules);
1069 
1070 	// register preloaded images
1071 
1072 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1073 		status_t status = register_preloaded_module_image(image);
1074 		if (status != B_OK) {
1075 			dprintf("Could not register image \"%s\": %s\n", image->name,
1076 				strerror(status));
1077 		}
1078 	}
1079 
1080 	sDisableUserAddOns = get_safemode_boolean(B_SAFEMODE_DISABLE_USER_ADD_ONS,
1081 		false);
1082 
1083 	add_debugger_command("modules", &dump_modules,
1084 		"list all known & loaded modules");
1085 
1086 	return B_OK;
1087 }
1088 
1089 
1090 //	#pragma mark - Exported Kernel API (public part)
1091 
1092 
1093 /*! This returns a pointer to a structure that can be used to
1094 	iterate through a list of all modules available under
1095 	a given prefix.
1096 	All paths will be searched and the returned list will
1097 	contain all modules available under the prefix.
1098 	The structure is then used by read_next_module_name(), and
1099 	must be freed by calling close_module_list().
1100 */
1101 void *
1102 open_module_list(const char *prefix)
1103 {
1104 	module_iterator *iterator;
1105 	uint32 i;
1106 
1107 	TRACE(("open_module_list(prefix = %s)\n", prefix));
1108 
1109 	if (sModulesHash == NULL) {
1110 		dprintf("open_module_list() called too early!\n");
1111 		return NULL;
1112 	}
1113 
1114 	iterator = (module_iterator *)malloc(sizeof(module_iterator));
1115 	if (!iterator)
1116 		return NULL;
1117 
1118 	memset(iterator, 0, sizeof(module_iterator));
1119 
1120 	iterator->prefix = strdup(prefix != NULL ? prefix : "");
1121 	if (iterator->prefix == NULL) {
1122 		free(iterator);
1123 		return NULL;
1124 	}
1125 	iterator->prefix_length = strlen(iterator->prefix);
1126 
1127 	if (gBootDevice > 0) {
1128 		// We do have a boot device to scan
1129 
1130 		// first, we'll traverse over the built-in modules
1131 		iterator->builtin_modules = true;
1132 		iterator->loaded_modules = false;
1133 
1134 		// put all search paths on the stack
1135 		for (i = 0; i < kNumModulePaths; i++) {
1136 			if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1137 				break;
1138 
1139 			KPath pathBuffer;
1140 			if (find_directory(kModulePaths[i], gBootDevice, true,
1141 					pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1142 				continue;
1143 
1144 			pathBuffer.UnlockBuffer();
1145 			pathBuffer.Append("kernel");
1146 
1147 			// Copy base path onto the iterator stack
1148 			char *path = strdup(pathBuffer.Path());
1149 			if (path == NULL)
1150 				continue;
1151 
1152 			size_t length = strlen(path);
1153 
1154 			// TODO: it would currently be nicer to use the commented
1155 			// version below, but the iterator won't work if the prefix
1156 			// is inside a module then.
1157 			// It works this way, but should be done better.
1158 #if 0
1159 			// Build path component: base path + '/' + prefix
1160 			size_t length = strlen(sModulePaths[i]);
1161 			char *path = (char *)malloc(length + iterator->prefix_length + 2);
1162 			if (path == NULL) {
1163 				// ToDo: should we abort the whole operation here?
1164 				//	if we do, don't forget to empty the stack
1165 				continue;
1166 			}
1167 
1168 			memcpy(path, sModulePaths[i], length);
1169 			path[length] = '/';
1170 			memcpy(path + length + 1, iterator->prefix,
1171 				iterator->prefix_length + 1);
1172 #endif
1173 
1174 			iterator_push_path_on_stack(iterator, path, length + 1);
1175 		}
1176 	} else {
1177 		// include loaded modules in case there is no boot device yet
1178 		iterator->builtin_modules = false;
1179 		iterator->loaded_modules = true;
1180 	}
1181 
1182 	return (void *)iterator;
1183 }
1184 
1185 
1186 /*!	Frees the cookie allocated by open_module_list() */
1187 status_t
1188 close_module_list(void *cookie)
1189 {
1190 	module_iterator *iterator = (module_iterator *)cookie;
1191 	const char *path;
1192 
1193 	TRACE(("close_module_list()\n"));
1194 
1195 	if (iterator == NULL)
1196 		return B_BAD_VALUE;
1197 
1198 	// free stack
1199 	while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL)
1200 		free((void *)path);
1201 
1202 	// close what have been left open
1203 	if (iterator->module_image != NULL)
1204 		put_module_image(iterator->module_image);
1205 
1206 	if (iterator->current_dir != NULL)
1207 		closedir(iterator->current_dir);
1208 
1209 	free(iterator->stack);
1210 	free((void *)iterator->current_path);
1211 	free((void *)iterator->current_module_path);
1212 
1213 	free(iterator->prefix);
1214 	free(iterator);
1215 
1216 	return B_OK;
1217 }
1218 
1219 
1220 /*!	Return the next module name from the available list, using
1221 	a structure previously created by a call to open_module_list().
1222 	Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
1223 	when done.
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 status_t
1259 get_next_loaded_module_name(uint32 *_cookie, char *buffer, size_t *_bufferSize)
1260 {
1261 	if (sModulesHash == NULL) {
1262 		dprintf("get_next_loaded_module_name() called too early!\n");
1263 		return B_ERROR;
1264 	}
1265 
1266 	//TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer));
1267 
1268 	if (_cookie == NULL || buffer == NULL || _bufferSize == NULL)
1269 		return B_BAD_VALUE;
1270 
1271 	status_t status = B_ENTRY_NOT_FOUND;
1272 	uint32 offset = *_cookie;
1273 
1274 	RecursiveLocker _(sModulesLock);
1275 
1276 	hash_iterator iterator;
1277 	hash_open(sModulesHash, &iterator);
1278 	struct module *module = (struct module *)hash_next(sModulesHash,
1279 		&iterator);
1280 
1281 	for (uint32 i = 0; module != NULL; i++) {
1282 		if (i >= offset) {
1283 			*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
1284 			*_cookie = i + 1;
1285 			status = B_OK;
1286 			break;
1287 		}
1288 		module = (struct module *)hash_next(sModulesHash, &iterator);
1289 	}
1290 
1291 	hash_close(sModulesHash, &iterator, false);
1292 
1293 	return status;
1294 }
1295 
1296 
1297 status_t
1298 get_module(const char *path, module_info **_info)
1299 {
1300 	module_image *moduleImage;
1301 	module *module;
1302 	status_t status;
1303 
1304 	TRACE(("get_module(%s)\n", path));
1305 
1306 	if (path == NULL)
1307 		return B_BAD_VALUE;
1308 
1309 	RecursiveLocker _(sModulesLock);
1310 
1311 	module = (struct module *)hash_lookup(sModulesHash, path);
1312 
1313 	// if we don't have it cached yet, search for it
1314 	if (module == NULL) {
1315 		module = search_module(path);
1316 		if (module == NULL) {
1317 			FATAL(("module: Search for %s failed.\n", path));
1318 			return B_ENTRY_NOT_FOUND;
1319 		}
1320 	}
1321 
1322 	if ((module->flags & B_BUILT_IN_MODULE) == 0) {
1323 		/* We now need to find the module_image for the module. This should
1324 		 * be in memory if we have just run search_module(), but may not be
1325 		 * if we are using cached information.
1326 		 * We can't use the module->module_image pointer, because it is not
1327 		 * reliable at this point (it won't be set to NULL when the module_image
1328 		 * is unloaded).
1329 		 */
1330 		if (get_module_image(module->file, &moduleImage) < B_OK)
1331 			return B_ENTRY_NOT_FOUND;
1332 
1333 		// (re)set in-memory data for the loaded module
1334 		module->info = moduleImage->info[module->offset];
1335 		module->module_image = moduleImage;
1336 
1337 		// the module image must not be unloaded anymore
1338 		if (module->flags & B_KEEP_LOADED)
1339 			module->module_image->keep_loaded = true;
1340 	}
1341 
1342 	// The state will be adjusted by the call to init_module
1343 	// if we have just loaded the file
1344 	if (module->ref_count == 0)
1345 		status = init_module(module);
1346 	else
1347 		status = B_OK;
1348 
1349 	if (status == B_OK) {
1350 		if (module->ref_count < 0)
1351 			panic("argl %s", path);
1352 		module->ref_count++;
1353 		*_info = module->info;
1354 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0
1355 		&& (module->flags & B_KEEP_LOADED) == 0)
1356 		put_module_image(module->module_image);
1357 
1358 	return status;
1359 }
1360 
1361 
1362 status_t
1363 put_module(const char *path)
1364 {
1365 	module *module;
1366 
1367 	TRACE(("put_module(path = %s)\n", path));
1368 
1369 	RecursiveLocker _(sModulesLock);
1370 
1371 	module = (struct module *)hash_lookup(sModulesHash, path);
1372 	if (module == NULL) {
1373 		FATAL(("module: We don't seem to have a reference to module %s\n",
1374 			path));
1375 		return B_BAD_VALUE;
1376 	}
1377 
1378 	if (module->ref_count == 0)
1379 		panic("module %s has no references.\n", path);
1380 
1381 	if ((module->flags & B_KEEP_LOADED) == 0) {
1382 		if (--module->ref_count == 0)
1383 			uninit_module(module);
1384 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0)
1385 		put_module_image(module->module_image);
1386 
1387 	return B_OK;
1388 }
1389