13 int Modules_LoadBuiltins();
14 int Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
15 int Module_LoadFile(char *Path, char *ArgString);
16 int Module_int_ResolveDeps(tModule *Info);
17 int Module_IsLoaded(char *Name);
21 extern int UDI_LoadDriver(void *Base);
23 extern void StartupPrint(char *Str);
24 extern tModule gKernelModules[];
25 extern void gKernelModulesEnd;
28 int giNumBuiltinModules = 0;
29 int giModuleSpinlock = 0;
30 tModule *gLoadedModules = NULL;
31 tModuleLoader *gModule_Loaders = NULL;
32 tModule *gLoadingModules = NULL;
36 * \brief Initialises a module
37 * \param Module Pointer to the module header
38 * \return Zero on success, eModuleErrors or -1 on error
39 * \retval -1 Returned if a dependency fails, or a circular dependency
41 * \retval 0 Returned on success
42 * \retval >0 Error code form the module's initialisation function
44 int Module_int_Initialise(tModule *Module)
51 ENTER("pModule", Module);
53 deps = Module->Dependencies;
55 // Check if the module has been loaded
56 for( mod = gLoadedModules; mod; mod = mod->Next )
58 if(mod == Module) LEAVE_RET('i', 0);
61 // Add to the "loading" (prevents circular deps)
62 Module->Next = gLoadingModules;
63 gLoadingModules = Module;
65 // Scan dependency list
66 for( j = 0; deps && deps[j]; j++ )
68 // Check if the module is already loaded
69 for( mod = gLoadedModules; mod; mod = mod->Next )
71 if(strcmp(deps[j], mod->Name) == 0)
74 if( mod ) continue; // Dependency is loaded, check the rest
76 // Ok, check if it's loading
77 for( mod = gLoadingModules->Next; mod; mod = mod->Next )
79 if(strcmp(deps[j], mod->Name) == 0)
83 Warning("[MOD ] Circular dependency detected");
87 // So, if it's not loaded, we better load it then
88 for( i = 0; i < giNumBuiltinModules; i ++ )
90 if( strcmp(deps[j], gKernelModules[i].Name) == 0 )
93 if( i == giNumBuiltinModules ) {
94 Warning("[MOD ] Dependency '%s' for module '%s' failed");
98 // Dependency is not loaded, so load it
99 ret = Module_int_Initialise( &gKernelModules[i] );
102 // The only "ok" error is NOTNEEDED
103 if(ret != MODULE_ERR_NOTNEEDED)
108 // All Dependencies OK? Initialise
109 StartupPrint(Module->Name);
110 Log("[MOD ] Initialising %p '%s' v%i.%i...",
111 Module, Module->Name,
112 Module->Version >> 8, Module->Version & 0xFF
115 ret = Module->Init(NULL);
116 if( ret != MODULE_ERR_OK ) {
117 Log("[MOD ] Loading Failed, all modules that depend on this will also fail");
120 case MODULE_ERR_MISC:
121 Log("[MOD ] Reason: Miscelanious");
123 case MODULE_ERR_NOTNEEDED:
124 Log("[MOD ] Reason: Module not needed (probably hardware not found)");
126 case MODULE_ERR_MALLOC:
127 Log("[MOD ] Reason: Error in malloc/realloc/calloc, probably not good");
130 Log("[MOD ] Reason - Unknown code %i", ret);
136 // Remove from loading list
137 gLoadingModules = gLoadingModules->Next;
139 // Add to loaded list
140 Module->Next = gLoadedModules;
141 gLoadedModules = Module;
147 * \brief Initialises builtin modules
149 int Modules_LoadBuiltins()
154 giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
155 giNumBuiltinModules /= sizeof(tModule);
157 for( i = 0; i < giNumBuiltinModules; i++ )
159 Module_int_Initialise( &gKernelModules[i] );
166 * \brief Registers a tModuleLoader with the kernel
167 * \param Loader Pointer to loader structure (must be persistent)
169 int Module_RegisterLoader(tModuleLoader *Loader)
171 if(!Loader) return 1;
173 Loader->Next = gModule_Loaders;
174 gModule_Loaders = Loader;
180 * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
181 * \brief Load a module from a memory location
183 int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
185 char path[VFS_MEMPATH_SIZE];
187 VFS_GetMemPath(path, Buffer, Length);
189 return Module_LoadFile( path, ArgString );
193 * \fn int Module_LoadFile(char *Path, char *ArgString)
194 * \brief Load a module from a file
196 int Module_LoadFile(char *Path, char *ArgString)
202 base = Binary_LoadKernel(Path);
206 Warning("Module_LoadFile: Unable to load '%s'", Path);
210 // Check for Acess Driver
211 if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
214 for( tmp = gModule_Loaders; tmp; tmp = tmp->Next)
216 if( tmp->Detector(base) == 0 ) continue;
218 return tmp->Loader(base);
222 // Check for EDI Driver
223 if( Binary_FindSymbol(base, "driver_init", NULL ) != 0 )
225 return Module_InitEDI( base ); // And intialise
229 // Unknown module type?, return error
232 Warning("Module_LoadFile: Module has neither a Module Info struct, nor an EDI entrypoint");
234 Warning("Module_LoadFile: Module does not have a Module Info struct");
239 // Check magic number
240 if(info->Magic != MODULE_MAGIC)
242 Warning("Module_LoadFile: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
246 // Check Architecture
247 if(info->Arch != MODULE_ARCH_ID)
249 Warning("Module_LoadFile: Module is for a different architecture");
253 // Resolve Dependencies
254 if( !Module_int_ResolveDeps(info) ) {
259 Log("Initialising %p '%s' v%i.%i...",
262 info->Version>>8, info->Version & 0xFF
266 //if( info->Init( ArgString ) != 0 )
267 if( info->Init( NULL ) == 0 )
274 LOCK( &giModuleSpinlock );
275 info->Next = gLoadedModules;
276 gLoadedModules = info;
277 RELEASE( &giModuleSpinlock );
283 * \fn int Module_int_ResolveDeps(tModule *Info)
284 * \brief Resolves the dependencies
286 * \note Currently does not resolve the dependencies, just checks them
288 int Module_int_ResolveDeps(tModule *Info)
290 char **names = Info->Dependencies;
292 // Walk dependencies array
293 for( ; *names; names++ )
295 // Check if the module is loaded
296 if( !Module_IsLoaded(*names) ) {
297 Warning("Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
305 * \fn int Module_IsLoaded(char *Name)
306 * \brief Checks if a module is loaded
307 * \param Name Name of module to find
309 int Module_IsLoaded(char *Name)
311 tModule *mod = gLoadedModules;
314 for( ; mod; mod = mod->Next )
316 // If found, return true
317 if(strcmp(mod->Name, Name) == 0)
320 // not found - return false