xref: /haiku/src/system/kernel/module.cpp (revision 90ca02568835b140b0e59de496a7f1f1d3513f67)
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 	if (recursive_lock_init(&sModulesLock, "modules rlock") < B_OK)
1098 		return B_ERROR;
1099 
1100 	sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash);
1101 	if (sModulesHash == NULL)
1102 		return B_NO_MEMORY;
1103 
1104 	sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare,
1105 		module_image_hash);
1106 	if (sModuleImagesHash == NULL)
1107 		return B_NO_MEMORY;
1108 
1109 	// register built-in modules
1110 
1111 	register_builtin_modules(sBuiltInModules);
1112 
1113 	// register preloaded images
1114 
1115 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1116 		status_t status = register_preloaded_module_image(image);
1117 		if (status != B_OK) {
1118 			dprintf("Could not register image \"%s\": %s\n", image->name,
1119 				strerror(status));
1120 		}
1121 	}
1122 
1123 	sDisableUserAddOns = get_safemode_boolean(B_SAFEMODE_DISABLE_USER_ADD_ONS,
1124 		false);
1125 
1126 	add_debugger_command("modules", &dump_modules,
1127 		"list all known & loaded modules");
1128 
1129 	return B_OK;
1130 }
1131 
1132 
1133 //	#pragma mark - Exported Kernel API (public part)
1134 
1135 
1136 /*! This returns a pointer to a structure that can be used to
1137 	iterate through a list of all modules available under
1138 	a given prefix that adhere to the specified suffix.
1139 	All paths will be searched and the returned list will
1140 	contain all modules available under the prefix.
1141 	The structure is then used by read_next_module_name(), and
1142 	must be freed by calling close_module_list().
1143 */
1144 void *
1145 open_module_list_etc(const char *prefix, const char *suffix)
1146 {
1147 	TRACE(("open_module_list(prefix = %s)\n", prefix));
1148 
1149 	if (sModulesHash == NULL) {
1150 		dprintf("open_module_list() called too early!\n");
1151 		return NULL;
1152 	}
1153 
1154 	module_iterator *iterator = (module_iterator *)malloc(
1155 		sizeof(module_iterator));
1156 	if (!iterator)
1157 		return NULL;
1158 
1159 	memset(iterator, 0, sizeof(module_iterator));
1160 
1161 	iterator->prefix = strdup(prefix != NULL ? prefix : "");
1162 	if (iterator->prefix == NULL) {
1163 		free(iterator);
1164 		return NULL;
1165 	}
1166 	iterator->prefix_length = strlen(iterator->prefix);
1167 
1168 	iterator->suffix = suffix;
1169 	if (suffix != NULL)
1170 		iterator->suffix_length = strlen(iterator->suffix);
1171 
1172 	if (gBootDevice > 0) {
1173 		// We do have a boot device to scan
1174 
1175 		// first, we'll traverse over the built-in modules
1176 		iterator->builtin_modules = true;
1177 		iterator->loaded_modules = false;
1178 
1179 		// put all search paths on the stack
1180 		for (uint32 i = 0; i < kNumModulePaths; i++) {
1181 			if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1182 				break;
1183 
1184 			KPath pathBuffer;
1185 			if (find_directory(kModulePaths[i], gBootDevice, true,
1186 					pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1187 				continue;
1188 
1189 			pathBuffer.UnlockBuffer();
1190 			pathBuffer.Append("kernel");
1191 
1192 			// Copy base path onto the iterator stack
1193 			char *path = strdup(pathBuffer.Path());
1194 			if (path == NULL)
1195 				continue;
1196 
1197 			size_t length = strlen(path);
1198 
1199 			// TODO: it would currently be nicer to use the commented
1200 			// version below, but the iterator won't work if the prefix
1201 			// is inside a module then.
1202 			// It works this way, but should be done better.
1203 #if 0
1204 			// Build path component: base path + '/' + prefix
1205 			size_t length = strlen(sModulePaths[i]);
1206 			char *path = (char *)malloc(length + iterator->prefix_length + 2);
1207 			if (path == NULL) {
1208 				// ToDo: should we abort the whole operation here?
1209 				//	if we do, don't forget to empty the stack
1210 				continue;
1211 			}
1212 
1213 			memcpy(path, sModulePaths[i], length);
1214 			path[length] = '/';
1215 			memcpy(path + length + 1, iterator->prefix,
1216 				iterator->prefix_length + 1);
1217 #endif
1218 
1219 			iterator_push_path_on_stack(iterator, path, length + 1);
1220 		}
1221 	} else {
1222 		// include loaded modules in case there is no boot device yet
1223 		iterator->builtin_modules = false;
1224 		iterator->loaded_modules = true;
1225 	}
1226 
1227 	return (void *)iterator;
1228 }
1229 
1230 
1231 void *
1232 open_module_list(const char *prefix)
1233 {
1234 	return open_module_list_etc(prefix, NULL);
1235 }
1236 
1237 
1238 /*!	Frees the cookie allocated by open_module_list() */
1239 status_t
1240 close_module_list(void *cookie)
1241 {
1242 	module_iterator *iterator = (module_iterator *)cookie;
1243 	const char *path;
1244 
1245 	TRACE(("close_module_list()\n"));
1246 
1247 	if (iterator == NULL)
1248 		return B_BAD_VALUE;
1249 
1250 	// free stack
1251 	while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL)
1252 		free((void *)path);
1253 
1254 	// close what have been left open
1255 	if (iterator->module_image != NULL)
1256 		put_module_image(iterator->module_image);
1257 
1258 	if (iterator->current_dir != NULL)
1259 		closedir(iterator->current_dir);
1260 
1261 	free(iterator->stack);
1262 	free((void *)iterator->current_path);
1263 	free((void *)iterator->current_module_path);
1264 
1265 	free(iterator->prefix);
1266 	free(iterator);
1267 
1268 	return B_OK;
1269 }
1270 
1271 
1272 /*!	Return the next module name from the available list, using
1273 	a structure previously created by a call to open_module_list().
1274 	Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
1275 	when done.
1276 */
1277 status_t
1278 read_next_module_name(void *cookie, char *buffer, size_t *_bufferSize)
1279 {
1280 	module_iterator *iterator = (module_iterator *)cookie;
1281 	status_t status;
1282 
1283 	TRACE(("read_next_module_name: looking for next module\n"));
1284 
1285 	if (iterator == NULL || buffer == NULL || _bufferSize == NULL)
1286 		return B_BAD_VALUE;
1287 
1288 	if (iterator->status < B_OK)
1289 		return iterator->status;
1290 
1291 	status = iterator->status;
1292 	recursive_lock_lock(&sModulesLock);
1293 
1294 	status = iterator_get_next_module(iterator, buffer, _bufferSize);
1295 
1296 	iterator->status = status;
1297 	recursive_lock_unlock(&sModulesLock);
1298 
1299 	TRACE(("read_next_module_name: finished with status %s\n",
1300 		strerror(status)));
1301 	return status;
1302 }
1303 
1304 
1305 /*!	Iterates through all loaded modules, and stores its path in "buffer".
1306 	ToDo: check if the function in BeOS really does that (could also mean:
1307 		iterate through all modules that are currently loaded; have a valid
1308 		module_image pointer, which would be hard to test for)
1309 */
1310 status_t
1311 get_next_loaded_module_name(uint32 *_cookie, char *buffer, size_t *_bufferSize)
1312 {
1313 	if (sModulesHash == NULL) {
1314 		dprintf("get_next_loaded_module_name() called too early!\n");
1315 		return B_ERROR;
1316 	}
1317 
1318 	//TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer));
1319 
1320 	if (_cookie == NULL || buffer == NULL || _bufferSize == NULL)
1321 		return B_BAD_VALUE;
1322 
1323 	status_t status = B_ENTRY_NOT_FOUND;
1324 	uint32 offset = *_cookie;
1325 
1326 	RecursiveLocker _(sModulesLock);
1327 
1328 	hash_iterator iterator;
1329 	hash_open(sModulesHash, &iterator);
1330 	struct module *module = (struct module *)hash_next(sModulesHash,
1331 		&iterator);
1332 
1333 	for (uint32 i = 0; module != NULL; i++) {
1334 		if (i >= offset) {
1335 			*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
1336 			*_cookie = i + 1;
1337 			status = B_OK;
1338 			break;
1339 		}
1340 		module = (struct module *)hash_next(sModulesHash, &iterator);
1341 	}
1342 
1343 	hash_close(sModulesHash, &iterator, false);
1344 
1345 	return status;
1346 }
1347 
1348 
1349 status_t
1350 get_module(const char *path, module_info **_info)
1351 {
1352 	module_image *moduleImage;
1353 	module *module;
1354 	status_t status;
1355 
1356 	TRACE(("get_module(%s)\n", path));
1357 
1358 	if (path == NULL)
1359 		return B_BAD_VALUE;
1360 
1361 	RecursiveLocker _(sModulesLock);
1362 
1363 	module = (struct module *)hash_lookup(sModulesHash, path);
1364 
1365 	// if we don't have it cached yet, search for it
1366 	if (module == NULL) {
1367 		module = search_module(path);
1368 		if (module == NULL) {
1369 			FATAL(("module: Search for %s failed.\n", path));
1370 			return B_ENTRY_NOT_FOUND;
1371 		}
1372 	}
1373 
1374 	if ((module->flags & B_BUILT_IN_MODULE) == 0) {
1375 		/* We now need to find the module_image for the module. This should
1376 		 * be in memory if we have just run search_module(), but may not be
1377 		 * if we are using cached information.
1378 		 * We can't use the module->module_image pointer, because it is not
1379 		 * reliable at this point (it won't be set to NULL when the module_image
1380 		 * is unloaded).
1381 		 */
1382 		if (get_module_image(module->file, &moduleImage) < B_OK)
1383 			return B_ENTRY_NOT_FOUND;
1384 
1385 		// (re)set in-memory data for the loaded module
1386 		module->info = moduleImage->info[module->offset];
1387 		module->module_image = moduleImage;
1388 
1389 		// the module image must not be unloaded anymore
1390 		if (module->flags & B_KEEP_LOADED)
1391 			module->module_image->keep_loaded = true;
1392 	}
1393 
1394 	// The state will be adjusted by the call to init_module
1395 	// if we have just loaded the file
1396 	if (module->ref_count == 0)
1397 		status = init_module(module);
1398 	else
1399 		status = B_OK;
1400 
1401 	if (status == B_OK) {
1402 		if (module->ref_count < 0)
1403 			panic("argl %s", path);
1404 		module->ref_count++;
1405 		*_info = module->info;
1406 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0
1407 		&& (module->flags & B_KEEP_LOADED) == 0)
1408 		put_module_image(module->module_image);
1409 
1410 	return status;
1411 }
1412 
1413 
1414 status_t
1415 put_module(const char *path)
1416 {
1417 	module *module;
1418 
1419 	TRACE(("put_module(path = %s)\n", path));
1420 
1421 	RecursiveLocker _(sModulesLock);
1422 
1423 	module = (struct module *)hash_lookup(sModulesHash, path);
1424 	if (module == NULL) {
1425 		FATAL(("module: We don't seem to have a reference to module %s\n",
1426 			path));
1427 		return B_BAD_VALUE;
1428 	}
1429 
1430 	if (module->ref_count == 0)
1431 		panic("module %s has no references.\n", path);
1432 
1433 	if ((module->flags & B_KEEP_LOADED) == 0) {
1434 		if (--module->ref_count == 0)
1435 			uninit_module(module);
1436 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0)
1437 		put_module_image(module->module_image);
1438 
1439 	return B_OK;
1440 }
1441