-Move some modules from i386 to generic space.
[newos.git] / kernel / module.c
bloba6e93c6671561c61f9329f88e0f21a0c6836b6c3
1 /*
2 ** Copyright 2001/02, Thomas Kurschel. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
4 */
6 //
7 // TODO:
8 // - "offsetof" macro is missing
9 // -> move it to a public place
11 #include <kernel/module.h>
12 #include <kernel/lock.h>
13 #include <kernel/heap.h>
14 #include <kernel/vm.h>
15 #include <kernel/cpu.h>
16 #include <kernel/debug.h>
17 #include <kernel/khash.h>
19 #include <kernel/elf.h>
21 #include <string.h>
23 #define debug_level_flow -1
24 #define debug_level_error 0
25 #define debug_level_info 0
27 #define DEBUG_MSG_PREFIX "MODULE -- "
29 #include <kernel/debug_ext.h>
31 #if 0
32 #include <kernel/bus/isa/isa.h>
33 #endif
37 #ifndef offsetof
38 #define offsetof(type, member) ((size_t)&(((type *)0)->member))
39 #endif
41 bool modules_disable_user_addons = false;
44 typedef enum {
45 module_loaded,
46 module_initializing,
47 module_ready,
48 module_uninitializing,
49 module_err_uninit
50 } module_state;
52 typedef struct module_info {
53 struct module_info *next;
54 struct module_image *image;
55 module_header *header;
56 int ref_count;
57 bool keep_loaded;
58 module_state state;
59 } module_info;
62 typedef struct module_image {
63 struct module_image *next;
64 int ref_count;
65 bool keep_loaded;
66 char *name;
67 char *path;
68 int base_path_id;
69 module_header **headers;
70 } module_image;
73 // XXX locking scheme: there is a global lock only; having several locks
74 // makes trouble if dependent modules get loaded concurrently ->
75 // they have to wait for each other, i.e. we need one lock per module;
76 // also we must detect circular references during init and not dead-lock
77 static recursive_lock modules_lock;
79 const char *const module_paths[] = {
80 "/boot/user-addons/modules",
81 "/boot/addons/modules"
84 #define num_module_paths (sizeof( module_paths ) / sizeof( module_paths[0] ))
86 #define MODULES_HASH_SIZE 16
88 void *modules_images[num_module_paths];
89 void *modules_list;
92 static int module_info_compare( void *a, const void *key )
94 module_info *module = a;
95 const char *name = key;
97 return strcmp( module->header->name, name );
100 static unsigned int module_info_hash( void *a, const void *key, unsigned int range )
102 module_info *module = a;
104 if( module != NULL )
105 return hash_hash_str( module->header->name ) % range;
106 else
107 return hash_hash_str( key ) % range;
110 static int module_image_compare( void *a, const void *key )
112 module_image *image = a;
113 const char *name = key;
115 return strcmp( image->name, name );
118 static unsigned int module_image_hash( void *a, const void *key, unsigned int range )
120 module_image *image = a;
122 if( image != NULL )
123 return hash_hash_str( image->name ) % range;
124 else
125 return hash_hash_str( key ) % range;
129 static inline int check_module_header( module_header *header )
131 if( header->version != MODULE_CURR_VERSION ) {
132 SHOW_ERROR( 0, "module %s has unsupported version (%i)", header->name, header->version );
133 return ERR_GENERAL;;
136 if( header->interface == NULL ) {
137 SHOW_ERROR( 0, "module %s has no public interface", header->name );
138 return ERR_GENERAL;
141 if( (header->flags & ~(MODULE_KEEP_LOADED)) != 0 ) {
142 SHOW_ERROR( 0, "module %s has unknown flag(s) set (%x)", header->name, header->flags );
143 return ERR_GENERAL;
146 return NO_ERROR;
150 static inline module_info *register_module( module_image *image, module_header *header )
152 module_info *module;
154 SHOW_FLOW( 3, "module %s in image %s", header->name, image->path );
156 if( check_module_header( header ) != NO_ERROR )
157 return NULL;
159 module = (module_info *)kmalloc( sizeof( module_info ));
161 if( module == NULL )
162 return NULL;
164 module->header = header;
165 module->image = image;
166 module->ref_count = 1;
167 module->keep_loaded = header->flags & MODULE_KEEP_LOADED;
168 image->keep_loaded |= module->keep_loaded;
169 module->state = module_loaded;
171 SHOW_FLOW0( 3, "adding to hash" );
172 if( hash_insert( modules_list, module ) != NO_ERROR ) {
173 kfree( module );
174 return NULL;
177 ++image->ref_count;
179 SHOW_FLOW0( 3, "done" );
181 return module;
184 static inline void unregister_module_image( module_image *image )
186 SHOW_FLOW( 3, "name=%s", image->name );
188 hash_remove( modules_images[image->base_path_id], image );
190 kfree( image->name );
191 kfree( image->path );
192 kfree( image );
195 static void put_module_image( module_image *image )
197 if( --image->ref_count == 0 ) {
198 SHOW_FLOW( 3, "image %s not in use anymore", image->name );
200 if( image->keep_loaded )
201 return;
203 SHOW_FLOW( 1, "unloading image... %s", image->path );
204 elf_unload_kspace( image->path );
205 SHOW_FLOW0( 1, "...done" );
207 unregister_module_image( image );
211 static inline void unregister_module( module_info *module )
213 SHOW_FLOW( 3, "%s", module->header->name );
214 hash_remove( modules_list, module );
216 put_module_image( module->image );
218 kfree( module );
222 static inline module_image *register_module_image_int( const char *image_name, const char *path,
223 int base_path_id, module_header **headers, bool keep_loaded )
225 module_image *image;
227 image = (module_image *)kmalloc( sizeof( module_image ));
229 if( image == NULL )
230 return NULL;
232 memset( image, 0, sizeof( image ));
233 image->ref_count = 1;
234 image->keep_loaded = keep_loaded;
235 image->name = kstrdup( image_name );
236 if( image->name == NULL )
237 goto err;
239 image->path = kstrdup( path );
240 if( image->path == NULL )
241 goto err2;
243 image->base_path_id = base_path_id;
244 image->headers = headers;
246 SHOW_FLOW( 3, "adding image to hash %i", base_path_id );
247 if( hash_insert( modules_images[base_path_id], image ) != NO_ERROR )
248 goto err3;
250 return image;
252 err3:
253 kfree( image->path );
254 err2:
255 kfree( image->name );
256 err:
257 kfree( image );
258 return NULL;
261 static module_image *register_module_image( const char *image_name, const char *path,
262 int base_path_id, module_header **headers, bool keep_loaded )
264 module_image *image;
265 module_header **header;
267 SHOW_FLOW( 3, "module %s", image_name );
269 image = register_module_image_int( image_name, path, base_path_id, headers, keep_loaded );
270 if( image == NULL )
271 return NULL;
273 for( header = image->headers; *header; ++header ) {
274 if( strncmp( (*header)->name, image->name, strlen( image->name )) != 0 )
275 SHOW_INFO( 0, "module %s stored in wrong image (%s)", (*header)->name, image->name );
278 return image;
281 static inline module_image *load_module_image( const char *image_name, const char *path, int base_path_id )
283 image_id file_image;
284 module_header **headers;
285 module_image *image;
287 SHOW_FLOW( 2, "loading %s", path );
289 file_image = elf_load_kspace( path, "" );
291 if( file_image < 0 ) {
292 SHOW_FLOW( 3, "couldn't load image %s (%s)", path, strerror( file_image ));
293 return NULL;
296 headers = (module_header **)elf_lookup_symbol( file_image, "modules" );
298 if( headers == NULL ) {
299 SHOW_INFO( 0, "image %s has no interface", path );
300 elf_unload_kspace( path );
301 return NULL;
304 SHOW_FLOW( 1, "loaded image %s", image_name );
306 image = register_module_image( image_name, path, base_path_id, headers, false );
308 if( image == NULL ) {
309 elf_unload_kspace( path );
310 return NULL;
313 return image;
316 static inline module_header *find_module_in_image( module_image *image, const char *name )
318 module_header **header;
320 for( header = image->headers; *header; ++header ) {
321 if( strcmp( (*header)->name, name ) == 0 ) {
322 SHOW_FLOW( 3, "found module %s in image %s", name, image->name );
323 return *header;
327 SHOW_FLOW( 3, "cannot find module %s in image %s", name, image->name );
328 return NULL;
331 static module_image *get_module_image( const char *name, size_t name_len, int base_path_id )
333 char path[SYS_MAX_PATH_LEN];
334 char *rel_name;
335 size_t total_len;
336 module_image *image;
338 if( base_path_id == 0 && modules_disable_user_addons ) {
339 SHOW_FLOW0( 3, "ignored - user add-ons are disabled" );
340 return NULL;
343 total_len = min( name_len, SYS_MAX_PATH_LEN ) + 1;
344 memcpy( path, name, total_len - 1 );
345 path[total_len - 1] = 0;
347 SHOW_FLOW( 3, "%s", path );
349 image = hash_lookup( modules_images[base_path_id], (void *)path );
351 if( image ) {
352 SHOW_FLOW0( 3, "image already loaded" );
353 ++image->ref_count;
354 return image;
357 total_len = strlen( module_paths[base_path_id] ) + 1 + name_len + 1;
359 if( total_len > SYS_MAX_PATH_LEN ) {
360 SHOW_FLOW0( 3, "ups, path too long" );
361 return NULL;
364 strcpy( path, module_paths[base_path_id] );
365 strcat( path, "/" );
366 rel_name = path + strlen( path );
368 strncat( path, name, name_len );
369 path[total_len - 1] = 0;
371 SHOW_FLOW( 3, "trying to load %s", path );
373 image = load_module_image( rel_name, path, base_path_id );
374 return image;
377 static module_info *search_module( const char *name )
379 int pos;
380 module_info *module;
382 SHOW_FLOW( 3, "name: %s", name );
384 module = hash_lookup( modules_list, (void *)name );
386 if( module != NULL ) {
387 SHOW_FLOW0( 3, "already loaded" );
389 ++module->ref_count;
390 return module;
393 SHOW_FLOW0( 3, "try to load it" );
394 pos = strlen( name );
396 while( pos >= 0 ) {
397 int i;
399 for( i = 0; i < (int)num_module_paths; ++i ) {
400 module_image *image;
402 image = get_module_image( name, pos, i );
404 if( image ) {
405 module_header *header;
407 SHOW_FLOW0( 3, "got image" );
409 header = find_module_in_image( image, name );
410 if( header ) {
411 SHOW_FLOW0( 3, "got header" );
413 module = register_module( image, header );
415 put_module_image( image );
416 return module;
419 put_module_image( image );
423 --pos;
425 while( pos > 0 && name[pos] != '/' )
426 --pos;
429 return NULL;
432 static inline int init_module( module_info *module )
434 int res;
436 switch( module->state ) {
437 case module_loaded:
438 module->state = module_initializing;
439 SHOW_FLOW( 3, "initing module %s... ", module->header->name );
440 res = module->header->init();
441 SHOW_FLOW( 3, "...done (%s)", strerror( res ));
443 if( !res )
444 module->state = module_ready;
445 else
446 module->state = module_loaded;
447 break;
449 case module_ready:
450 res = NO_ERROR;
451 break;
453 case module_initializing:
454 SHOW_ERROR( 0, "circular reference to %s", module->header->name );
455 res = ERR_GENERAL;
456 break;
458 case module_uninitializing:
459 SHOW_ERROR( 0, "tried to load module %s which is currently unloading", module->header->name );
460 res = ERR_GENERAL;
461 break;
463 case module_err_uninit:
464 SHOW_INFO( 0, "cannot load module %s because its earlier unloading failed", module->header->name );
465 res = ERR_GENERAL;
466 break;
468 default:
469 res = ERR_GENERAL;
472 return res;
475 static inline int uninit_module( module_info *module )
477 switch( module->state ) {
478 case module_loaded:
479 return NO_ERROR;
481 case module_initializing:
482 panic( "Trying to unload module %s which is initializing",
483 module->header->name );
484 return ERR_GENERAL;
486 case module_uninitializing:
487 panic( "Trying to unload module %s which is un-initializing", module->header->name );
488 return ERR_GENERAL;
490 case module_ready:
492 int res;
494 module->state = module_uninitializing;
496 SHOW_FLOW( 2, "uniniting module %s...", module->header->name );
497 res = module->header->uninit();
498 SHOW_FLOW( 2, "...done (%s)", strerror( res ));
500 if( res == NO_ERROR ) {
501 module->state = module_loaded;
502 return NO_ERROR;
505 SHOW_ERROR( 0, "Error unloading module %s (%i)", module->header->name, res );
508 module->state = module_err_uninit;
509 module->keep_loaded = true;
510 module->image->keep_loaded = true;
512 // fall through
513 default:
514 return ERR_GENERAL;
518 static int put_module_info( module_info *module )
520 int res;
522 if( --module->ref_count != 0 )
523 return NO_ERROR;
525 SHOW_FLOW( 2, "module %s not in use anymore", module->header->name );
527 if( module->keep_loaded )
528 return NO_ERROR;
530 res = uninit_module( module );
532 if( res == NO_ERROR )
533 unregister_module( module );
535 return res;
538 int module_get( const char *name, int flags, void **interface )
540 module_info *module;
541 int res;
543 SHOW_FLOW( 0, "name=%s, flags=%i", name, flags );
545 if( flags != 0 )
546 return ERR_INVALID_ARGS;
548 recursive_lock_lock( &modules_lock );
550 module = search_module( name );
552 if( !module ) {
553 SHOW_FLOW( 3, "couldn't find module %s", name );
554 res = ERR_NOT_FOUND;
555 goto err;
558 SHOW_FLOW0( 3, "make sure module is ready" );
559 res = init_module( module );
561 if( res != NO_ERROR )
562 goto err2;
564 SHOW_FLOW0( 3, "module's ready to use" );
566 *interface = module->header->interface;
568 recursive_lock_unlock( &modules_lock );
569 return res;
571 err2:
572 put_module_info( module );
573 err:
574 recursive_lock_unlock( &modules_lock );
575 return res;
578 int module_put( const char *name )
580 module_info *module;
581 int res;
583 SHOW_FLOW( 0, "name=%s", name );
585 recursive_lock_lock( &modules_lock );
587 module = hash_lookup( modules_list, (void *)name );
588 if( module == NULL ) {
589 res = ERR_NOT_FOUND;
590 goto err;
593 res = put_module_info( module );
595 err:
596 recursive_lock_unlock( &modules_lock );
597 return res;
601 typedef struct module_iterator {
602 char *prefix;
603 module_image *cur_image;
604 module_header **cur_header;
605 int base_path_id;
606 struct module_dir_iterator *base_dir, *cur_dir;
607 int err;
608 int prefix_pos;
609 unsigned int prefix_base_path_id;
610 } module_iterator;
612 typedef struct module_dir_iterator {
613 struct module_dir_iterator *parent_dir, *sub_dir;
614 char *name;
615 int file;
616 } module_dir_iterator;
619 modules_cookie module_open_list( const char *prefix )
621 module_iterator *iter;
623 SHOW_FLOW( 3, "prefix: %s", prefix );
625 if( (iter = kmalloc( sizeof( *iter ))) == NULL )
626 return NULL;
628 iter->prefix = kstrdup( prefix );
629 if( iter == NULL ) {
630 kfree( iter );
631 return NULL;
634 /*iter->cur_image = module_sys_image;
635 ++module_sys_image->ref_count;
636 iter->cur_header = iter->cur_image->headers;*/
637 iter->cur_image = NULL;
638 iter->cur_header = NULL;
640 iter->base_path_id = -1;
641 iter->base_dir = iter->cur_dir = NULL;
642 iter->err = NO_ERROR;
643 iter->prefix_pos = strlen( prefix );
645 iter->prefix_base_path_id = 0;
647 return (modules_cookie)iter;
651 static inline int module_enter_image( module_iterator *iter, const char *image_name )
653 module_image *image;
655 SHOW_FLOW( 3, "%s", image_name );
657 image = get_module_image( image_name, strlen( image_name ), iter->base_path_id );
659 if( image == NULL ) {
660 SHOW_FLOW( 3, "cannot get image %s", image_name );
662 return NO_ERROR;
665 iter->cur_image = image;
666 iter->cur_header = image->headers;
668 SHOW_FLOW( 3, "entered image %s", image_name );
669 return NO_ERROR;
672 static inline int module_create_dir_iterator( module_iterator *iter, int file, const char *name )
674 module_dir_iterator *dir;
676 dir = kmalloc( sizeof( *dir ));
677 if( dir == NULL )
678 return ERR_NO_MEMORY;
680 dir->name = kstrdup( name );
681 if( dir->name == NULL ) {
682 kfree( dir );
683 return ERR_NO_MEMORY;
686 dir->file = file;
688 dir->sub_dir = NULL;
689 dir->parent_dir = iter->cur_dir;
691 if( iter->cur_dir )
692 iter->cur_dir->sub_dir = dir;
693 else
694 iter->base_dir = dir;
696 iter->cur_dir = dir;
698 SHOW_FLOW( 3, "created dir iterator for %s", name );
699 return NO_ERROR;
702 static inline int module_enter_dir( module_iterator *iter, const char *path, const char *name )
704 int file;
705 int res;
707 file = sys_opendir( path );
708 if( file < 0 ) {
709 SHOW_FLOW( 3, "couldn't open directory %s (%s)", path, strerror( file ));
711 // there are so many errors for "not found" that we don't bother
712 // and always assume that the directory suddenly disappeared
713 return NO_ERROR;
716 res = module_create_dir_iterator( iter, file, name );
717 if( res != NO_ERROR ) {
718 sys_closedir( file );
719 return ERR_NO_MEMORY;
722 SHOW_FLOW( 3, "entered directory %s", path );
723 return NO_ERROR;
727 static inline void destroy_dir_iterator( module_iterator *iter )
729 module_dir_iterator *dir;
731 dir = iter->cur_dir;
733 SHOW_FLOW( 3, "destroying directory iterator for sub-dir %s", dir->name );
735 if( dir->parent_dir )
736 dir->parent_dir->sub_dir = NULL;
738 iter->cur_dir = dir->parent_dir;
740 kfree( dir->name );
741 kfree( dir );
745 static inline void module_leave_dir( module_iterator *iter )
747 module_dir_iterator *parent_dir;
749 SHOW_FLOW( 3, "leaving directory %s", iter->cur_dir->name );
751 parent_dir = iter->cur_dir->parent_dir;
753 sys_closedir( iter->cur_dir->file );
754 destroy_dir_iterator( iter );
756 iter->cur_dir = parent_dir;
759 static void compose_path( char *path, module_iterator *iter, const char *name, bool full_path )
761 module_dir_iterator *dir;
763 if( full_path ) {
764 strlcpy( path, iter->base_dir->name, SYS_MAX_PATH_LEN );
765 strlcat( path, "/", SYS_MAX_PATH_LEN );
766 } else {
767 strlcpy( path, iter->prefix, SYS_MAX_PATH_LEN );
768 if( *iter->prefix )
769 strlcat( path, "/", SYS_MAX_PATH_LEN );
772 for( dir = iter->base_dir->sub_dir; dir; dir = dir->sub_dir ) {
773 strlcat( path, dir->name, SYS_MAX_PATH_LEN );
774 strlcat( path, "/", SYS_MAX_PATH_LEN );
777 strlcat( path, name, SYS_MAX_PATH_LEN );
779 SHOW_FLOW( 3, "name: %s, %s -> %s", name,
780 full_path ? "full path" : "relative path",
781 path );
785 static inline int module_traverse_dir( module_iterator *iter )
787 int res;
788 struct file_stat stat;
789 char name[SYS_MAX_NAME_LEN];
790 char path[SYS_MAX_PATH_LEN];
792 SHOW_FLOW( 3, "scanning %s", iter->cur_dir->name );
794 if( (res = sys_readdir( iter->cur_dir->file, name, sizeof( name ))) <= 0 ) {
795 SHOW_FLOW( 3, "got error: %s", strerror( res ));
796 module_leave_dir( iter );
797 return NO_ERROR;
800 SHOW_FLOW( 3, "got %s", name );
802 if( strcmp( name, "." ) == 0 ||
803 strcmp( name, ".." ) == 0 )
804 return NO_ERROR;
806 // currently, sys_read returns an error if buffer is too small
807 // I don't know the official specification, so it's always safe
808 // to add a trailing end-of-string
809 name[sizeof(name) - 1] = 0;
811 compose_path( path, iter, name, true );
813 if( (res = sys_rstat( path, &stat)) != NO_ERROR )
814 return res;
816 switch( stat.type ) {
817 case STREAM_TYPE_FILE:
818 compose_path( path, iter, name, false );
820 return module_enter_image( iter, path );
822 case STREAM_TYPE_DIR:
823 return module_enter_dir( iter, path, name );
825 default:
826 SHOW_FLOW( 3, "entry %s not a file nor a directory - ignored", name );
827 return NO_ERROR;
832 static inline int module_enter_master_image( module_iterator *iter )
834 module_image *image;
836 SHOW_FLOW0( 3, "" );
838 if( iter->prefix_base_path_id >= num_module_paths ) {
840 SHOW_FLOW0( 3, "reducing image name" );
841 --iter->prefix_pos;
843 while(
844 iter->prefix_pos > 0 &&
845 iter->prefix[iter->prefix_pos] != '/' )
847 --iter->prefix_pos;
850 iter->prefix_base_path_id = 0;
852 if( iter->prefix_pos < 0 ) {
853 SHOW_FLOW0( 3, "no possible master image left" );
854 return NO_ERROR;
858 SHOW_FLOW0( 3, "trying new image" );
859 image = get_module_image( iter->prefix, iter->prefix_pos, iter->prefix_base_path_id );
861 ++iter->prefix_base_path_id;
863 if( image ) {
864 SHOW_FLOW( 3, "got image %s", image->name );
866 iter->cur_image = image;
867 iter->cur_header = image->headers;
870 return NO_ERROR;
873 static inline int module_enter_base_path( module_iterator *iter )
875 char path[SYS_MAX_PATH_LEN];
876 int res;
878 ++iter->base_path_id;
880 if( iter->base_path_id >= (int)num_module_paths ) {
881 SHOW_FLOW0( 3, "no locations left" );
882 return ERR_NOT_FOUND;
885 SHOW_FLOW( 3, "checking new base path (%s)", module_paths[iter->base_path_id] );
887 if( iter->base_path_id == 0 && modules_disable_user_addons ) {
888 SHOW_FLOW0( 3, "ignoring user add-ons (they are disabled)" );
889 return NO_ERROR;
892 strcpy( path, module_paths[iter->base_path_id] );
893 if( *iter->prefix ) {
894 strcat( path, "/" );
895 strlcat( path, iter->prefix, sizeof( path ));
898 res = module_enter_dir( iter, path, path );
900 return res;
903 static inline bool iter_check_module_header( module_iterator *iter )
905 module_info *module;
906 module_image *tmp_image;
907 const char *name;
909 if( *iter->cur_header == NULL ) {
910 SHOW_FLOW0( 3, "reached end of modules list in image" );
912 put_module_image( iter->cur_image );
914 iter->cur_header = NULL;
915 iter->cur_image = NULL;
917 return false;
920 name = (*iter->cur_header)->name;
922 SHOW_FLOW( 3, "checking %s", name );
924 if( strlen( name ) < strlen( iter->prefix ) ||
925 memcmp( name, iter->prefix, strlen( iter->prefix )) != 0 )
927 SHOW_FLOW( 3, "module %s has wrong prefix", name );
929 ++iter->cur_header;
930 return false;
933 module = search_module( name );
935 if( module == NULL ) {
936 SHOW_FLOW( 3, "couldn't get module %s -> must be broken", name );
938 ++iter->cur_header;
939 return false;
942 SHOW_FLOW0( 3, "get rid of image" );
944 tmp_image = module->image;
945 ++tmp_image->ref_count;
947 put_module_info( module );
949 if( iter->base_path_id >= 0 ) {
950 if( strlen( tmp_image->name ) < strlen( iter->prefix ) ||
951 tmp_image->base_path_id != iter->base_path_id )
953 if( strlen( tmp_image->name ) < strlen( iter->prefix ))
954 SHOW_FLOW( 3, "image name (%s) is shorter then prefix -> already scanned",
955 tmp_image->name );
956 else
957 SHOW_FLOW( 3, "image (%s) is from wrong base path", tmp_image->name );
959 put_module_image( tmp_image );
960 ++iter->cur_header;
961 return false;
965 put_module_image( tmp_image );
967 SHOW_FLOW( 3, "found module %s", name );
968 return true;
971 int read_next_module_name( modules_cookie cookie, char *buf, size_t *bufsize )
973 module_iterator *iter = (module_iterator *)cookie;
974 int res;
976 if( !iter )
977 return ERR_INVALID_ARGS;
979 res = iter->err;
981 while( res == NO_ERROR ) {
982 if( iter->cur_header ) {
983 SHOW_FLOW0( 3, "having image to scan" );
985 if( iter_check_module_header( iter )) {
986 strlcpy( buf, (*iter->cur_header)->name, *bufsize );
987 *bufsize = strlen( buf );
989 ++iter->cur_header;
991 res = NO_ERROR;
992 break;
994 } else {
995 SHOW_FLOW0( 3, "looking for new image" );
997 if( iter->cur_dir == NULL ) {
998 if( iter->prefix_pos >= 0 )
999 res = module_enter_master_image( iter );
1000 else
1001 res = module_enter_base_path( iter );
1002 } else
1003 res = module_traverse_dir( iter );
1007 iter->err = res;
1009 SHOW_FLOW( 3, "finished with status %s", strerror( iter->err ));
1010 return iter->err;
1014 int close_module_list( modules_cookie cookie )
1016 module_iterator *iter = (module_iterator *)cookie;
1018 SHOW_FLOW0( 3, "" );
1020 if( !iter )
1021 return ERR_INVALID_ARGS;
1023 while( iter->cur_dir )
1024 module_leave_dir( iter );
1026 kfree( iter->prefix );
1027 kfree( iter );
1028 return NO_ERROR;
1031 module_header *dummy[] = { NULL };
1034 int module_init( kernel_args *ka, module_header **sys_module_headers )
1036 unsigned int i;
1038 SHOW_FLOW0( 0, "" );
1039 recursive_lock_create( &modules_lock );
1041 modules_list = hash_init( MODULES_HASH_SIZE,
1042 offsetof( module_info, next ),
1043 module_info_compare, module_info_hash );
1045 if( modules_list == NULL )
1046 return ERR_NO_MEMORY;
1048 for( i = 0; i < num_module_paths; ++i ) {
1049 modules_images[i] = hash_init( MODULES_HASH_SIZE,
1050 offsetof( module_image, next ),
1051 module_image_compare, module_image_hash);
1053 if( modules_images[i] == NULL )
1054 return ERR_NO_MEMORY;
1057 if( sys_module_headers == NULL )
1058 sys_module_headers = dummy;
1060 if( register_module_image( "", "(built-in)", 0, sys_module_headers, true ) == NULL )
1061 return ERR_NO_MEMORY;
1063 // XXX: VERY VERY BAD LINK HACK!
1064 // we need to link all libc functions into kernel, but there are
1065 // some user space functions in libc that obviously must not be
1066 // added to the kernel image -> split libc in common and user space
1067 // only lib and force linking of entire common lib into kernel via
1068 // --whole-archive
1070 // meanwhile, we make sure that nothing is missing by referencing all
1071 // functions manually (ouch!)
1073 #if 1
1075 const char *dummy;
1077 dummy = strerror( NO_ERROR );
1079 #endif
1081 #if 0
1083 isa_bus_manager *isa_interface;
1084 int res;
1085 int i;
1086 void *iterator;
1087 char module_name[SYS_MAX_PATH_LEN];
1088 size_t name_len;
1089 const char prefix[] = "bus_managers";
1090 modules_cookie modules_cookie;
1092 if( (res = module_get( ISA_MODULE_NAME, 0, (void **)&isa_interface )) != NO_ERROR )
1093 dprintf( "Cannot load isa module (%s)", strerror( res ));
1094 else {
1095 for( i = 'A'; i <= 'Z'; ++i )
1096 isa_interface->write_io_8( 0xe9, i );
1098 module_put( ISA_MODULE_NAME );
1101 dprintf( "Getting modules with prefix %s", prefix );
1102 modules_cookie = module_open_list( prefix );
1104 while( name_len = sizeof( module_name ),
1105 read_next_module_name( modules_cookie, module_name, &name_len ) == NO_ERROR )
1107 dprintf( "Found module %s", module_name );
1110 close_module_list( modules_cookie );
1111 dprintf( "done" );
1113 #endif
1115 #if 0
1117 void *interface;
1119 module_get( "busses/ide/ide_isa", 0, &interface );
1121 #endif
1123 return NO_ERROR;