11 #define MODULE_FLAG_LOADERROR 0x1
14 int Module_int_Initialise(tModule *Module, const char *ArgString);
15 void Modules_int_GetBuiltinArray(void);
16 void Modules_LoadBuiltins(void);
17 void Modules_SetBuiltinParams(const char *Name, char *ArgString);
18 int Modules_InitialiseBuiltin(const char *Name);
19 // int Module_RegisterLoader(tModuleLoader *Loader);
20 // int Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
21 // int Module_LoadFile(char *Path, char *ArgString);
22 int Module_int_ResolveDeps(tModule *Info);
23 int Module_IsLoaded(const char *Name);
24 // int Module_EnsureLoaded(const char *Name);
27 EXPORT(Module_RegisterLoader);
31 extern int UDI_LoadDriver(void *Base);
33 extern void StartupPrint(const char *Str);
34 extern tModule gKernelModules;
35 extern tModule gKernelModulesEnd;
38 int giNumBuiltinModules = 0;
39 tShortSpinlock glModuleSpinlock;
40 tModule *gLoadedModules = NULL;
41 tModuleLoader *gModule_Loaders = NULL;
42 tModule *gLoadingModules = NULL;
43 tModule **gapBuiltinModules = NULL;
44 char **gasBuiltinModuleArgs;
48 * \brief Initialises a module
49 * \param Module Pointer to the module header
50 * \param ArgString Comma separated list of module arguments
51 * \return Zero on success, eModuleErrors or -1 on error
52 * \retval -1 Returned if a dependency fails, or a circular dependency
54 * \retval 0 Returned on success
55 * \retval >0 Error code form the module's initialisation function
57 int Module_int_Initialise(tModule *Module, const char *ArgString)
65 ENTER("pModule", Module);
66 LOG("Module->Magic = 0x%x", Module->Magic);
67 if(Module->Magic != MODULE_MAGIC) {
70 "Module %p is no a valid Acess2 module (0x%08x != 0x%08x)",
71 Module, Module->Magic, MODULE_MAGIC
73 LEAVE('i', MODULE_ERR_BADMODULE);
74 return MODULE_ERR_BADMODULE;
76 LOG("Module->Name = %p \"%s\"", Module->Name, Module->Name);
78 if(Module->Arch != MODULE_ARCH_ID) {
81 "Module %p (%s) is for another architecture (%i)",
82 Module, Module->Name, Module->Arch
84 LEAVE('i', MODULE_ERR_BADMODULE);
85 return MODULE_ERR_BADMODULE;
88 LOG("Module->Flags = %x", Module->Flags);
89 if(Module->Flags & MODULE_FLAG_LOADERROR ) {
90 Log_Warning("Module", "%s has already attempted to load and encountered errors", Module->Name);
91 LEAVE('i', MODULE_ERR_MISC);
92 return MODULE_ERR_MISC;
95 deps = Module->Dependencies;
97 // Check if the module has been loaded
98 for( mod = gLoadedModules; mod; mod = mod->Next )
100 if(mod == Module) LEAVE_RET('i', 0);
103 // Add to the "loading" (prevents circular deps)
104 Module->Next = gLoadingModules;
105 gLoadingModules = Module;
107 // Scan dependency list
108 for( j = 0; deps && deps[j]; j++ )
110 // Check if the module is already loaded
111 for( mod = gLoadedModules; mod; mod = mod->Next )
113 if(strcmp(deps[j], mod->Name) == 0)
116 if( mod ) continue; // Dependency is loaded, check the rest
118 // Ok, check if it's loading
119 for( mod = gLoadingModules->Next; mod; mod = mod->Next )
121 if(strcmp(deps[j], mod->Name) == 0)
125 Log_Warning("Module", "Circular dependency detected (%s and %s)",
126 mod->Name, Module->Name);
130 // So, if it's not loaded, we better load it then
131 for( i = 0; i < giNumBuiltinModules; i ++ )
133 if( strcmp(deps[j], gapBuiltinModules[i]->Name) == 0 )
136 if( i == giNumBuiltinModules ) {
137 Log_Warning("Module", "Dependency '%s' for module '%s' failed",
138 deps[j], Module->Name);
142 // Dependency is not loaded, so load it
143 ret = Module_int_Initialise(
144 gapBuiltinModules[i],
145 gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL
149 // The only "ok" error is NOTNEEDED
150 if(ret != MODULE_ERR_NOTNEEDED)
155 // All Dependencies OK? Initialise
156 StartupPrint(Module->Name);
157 Log_Log("Module", "Starting %p '%s' v%i.%i",
158 Module, Module->Name,
159 Module->Version >> 8, Module->Version & 0xFF
163 args = str_split( ArgString, ',' );
167 ret = Module->Init(args);
171 // Remove from loading list
172 gLoadingModules = gLoadingModules->Next;
174 if( ret != MODULE_ERR_OK ) {
177 case MODULE_ERR_MISC:
178 Log_Warning("Module", "Unable to load, reason: Miscelanious");
180 case MODULE_ERR_NOTNEEDED:
181 // Log_Debug("Module", "Unable to load, reason: Module not needed");
183 case MODULE_ERR_MALLOC:
184 Log_Warning("Module", "Unable to load, reason: Error in malloc/realloc/calloc, probably not good");
187 Log_Warning("Module", "Unable to load reason - Unknown code %i", ret);
190 Module->Flags |= MODULE_FLAG_LOADERROR;
194 LOG("ret = %i", ret);
196 // Add to loaded list
197 SHORTLOCK( &glModuleSpinlock );
198 Module->Next = gLoadedModules;
199 gLoadedModules = Module;
200 SHORTREL( &glModuleSpinlock );
206 * \brief Scans the builtin modules and creates an array of them
208 void Modules_int_GetBuiltinArray(void)
214 module = &gKernelModules;
216 while( (tVAddr)module < (tVAddr)&gKernelModulesEnd )
218 if(module->Magic == MODULE_MAGIC) {
223 module = (void*)( (tVAddr)module + 4 );
227 giNumBuiltinModules = i;
228 gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) );
229 gapBuiltinModules = malloc( giNumBuiltinModules * sizeof(tModule*) );
233 module = &gKernelModules;
235 while( (tVAddr)module < (tVAddr)&gKernelModulesEnd )
237 if(module->Magic == MODULE_MAGIC) {
238 gapBuiltinModules[i] = module;
243 module = (void*)( (tVAddr)module + 4 );
248 * \brief Initialises builtin modules
250 void Modules_LoadBuiltins()
254 if( !gapBuiltinModules )
255 Modules_int_GetBuiltinArray();
257 for( i = 0; i < giNumBuiltinModules; i++ )
259 Module_int_Initialise(
260 gapBuiltinModules[i],
261 (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL)
265 if( gasBuiltinModuleArgs != NULL )
266 free(gasBuiltinModuleArgs);
270 * \brief Initialise a builtin module given it's name
272 * E.g. Used by VTerm to load an alternate video driver at runtime
274 int Modules_InitialiseBuiltin(const char *Name)
278 // Check if it's loaded
279 if( Module_IsLoaded(Name) )
282 if( !gapBuiltinModules )
283 Modules_int_GetBuiltinArray();
285 for( i = 0; i < giNumBuiltinModules; i++ )
287 if( strcmp(gapBuiltinModules[i]->Name, Name) == 0 ) {
288 return Module_int_Initialise(gapBuiltinModules[i],
289 (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL)
297 * \brief Sets the parameters for a builtin module
299 void Modules_SetBuiltinParams(const char *Name, char *ArgString)
303 if( gasBuiltinModuleArgs == NULL )
305 Modules_int_GetBuiltinArray();
308 // I hate expensive scans
309 for( i = 0; i < giNumBuiltinModules; i++ )
311 if(strcmp( gapBuiltinModules[i]->Name, Name ) == 0) {
312 gasBuiltinModuleArgs[i] = ArgString;
317 Log_Warning("Modules", "Unknown builtin kernel module '%s'", Name);
321 * \brief Registers a tModuleLoader with the kernel
322 * \param Loader Pointer to loader structure (must be persistent)
324 int Module_RegisterLoader(tModuleLoader *Loader)
326 if(!Loader) return 1;
328 Loader->Next = gModule_Loaders;
329 gModule_Loaders = Loader;
335 * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
336 * \brief Load a module from a memory location
338 int Module_LoadMem(void *Buffer, Uint Length, const char *ArgString)
340 char path[VFS_MEMPATH_SIZE];
342 VFS_GetMemPath(path, Buffer, Length);
344 return Module_LoadFile( path, ArgString );
348 * \fn int Module_LoadFile(const char *Path, const char *ArgString)
349 * \brief Load a module from a file
351 int Module_LoadFile(const char *Path, const char *ArgString)
355 tModuleLoader *loader = NULL;
358 base = Binary_LoadKernel(Path);
362 Log_Warning("Module", "Module_LoadFile - Unable to load '%s'", Path);
366 // TODO: I need a way of relocating the dependencies before everything else, so
367 // they can be resolved before any other link errors
368 if( !Binary_Relocate(base) ) {
369 Log_Warning("Module", "Relocation of module %s failed", Path);
374 // Check for Acess Driver
375 if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
377 for( loader = gModule_Loaders; loader; loader = loader->Next)
379 if( loader->Detector(base) )
383 // Unknown module type?, return error
386 Log_Warning("Module", "Module '%s' does not have a Module Info struct", Path);
391 if( !Module_int_ResolveDeps(info) ) {
392 Log_Warning("Module", "Dependencies not met for '%s'", Path);
397 // Initialise (and register)
398 if( loader ? loader->Loader(base) : Module_int_Initialise( info, ArgString ) )
408 * \fn int Module_int_ResolveDeps(tModule *Info)
409 * \brief Resolves the dependencies
411 * \note Currently does not resolve the dependencies, just checks them
413 int Module_int_ResolveDeps(tModule *Info)
415 const char **names = Info->Dependencies;
417 // Walk dependencies array
418 for( ; *names; names++ )
420 // Check if the module is loaded
421 if( !Module_IsLoaded(*names) ) {
422 Log_Warning("Module", "Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
430 * \fn int Module_IsLoaded(const char *Name)
431 * \brief Checks if a module is loaded
432 * \param Name Name of module to find
434 int Module_IsLoaded(const char *Name)
436 tModule *mod = gLoadedModules;
439 for( ; mod; mod = mod->Next )
441 // If found, return true
442 if(strcmp(mod->Name, Name) == 0)
445 // not found - return false
450 * \brief Load a module if needed
452 int Module_EnsureLoaded(const char *Name)
454 if( Module_IsLoaded(Name) )
457 if( Modules_InitialiseBuiltin(Name) == 0 )
460 // TODO: Load from a file?