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