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