11 #define MODULE_FLAG_LOADERROR 0x1
14 int Module_int_Initialise(tModule *Module, const char *ArgString);
15 size_t Modules_int_PopulateBuiltins(tModule **Array);
16 void Modules_int_GetBuiltinArray(void);
17 void Modules_LoadBuiltins(void);
18 void Modules_SetBuiltinParams(const char *Name, char *ArgString);
19 int Modules_InitialiseBuiltin(const char *Name);
20 // int Module_RegisterLoader(tModuleLoader *Loader);
21 // int Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
22 // int Module_LoadFile(char *Path, char *ArgString);
23 int Module_int_ResolveDeps(tModule *Info);
24 int Module_IsLoaded(const char *Name);
25 // int Module_EnsureLoaded(const char *Name);
28 EXPORT(Module_RegisterLoader);
32 extern int UDI_LoadDriver(void *Base);
34 extern void StartupPrint(const char *Str);
35 extern tModule gKernelModules;
36 extern tModule gKernelModulesEnd;
39 int giNumBuiltinModules = 0;
40 tShortSpinlock glModuleSpinlock;
41 tModule *gLoadedModules = NULL;
42 tModuleLoader *gModule_Loaders = NULL;
43 tModule *gLoadingModules = NULL;
44 tModule **gapBuiltinModules = NULL;
45 char **gasBuiltinModuleArgs;
49 * \brief Initialises a module
50 * \param Module Pointer to the module header
51 * \param ArgString Comma separated list of module arguments
52 * \return Zero on success, eModuleErrors or -1 on error
53 * \retval -1 Returned if a dependency fails, or a circular dependency
55 * \retval 0 Returned on success
56 * \retval >0 Error code form the module's initialisation function
58 int Module_int_Initialise(tModule *Module, const char *ArgString)
66 ENTER("pModule", Module);
67 LOG("Module->Magic = 0x%x", Module->Magic);
68 if(Module->Magic != MODULE_MAGIC) {
71 "Module %p is no a valid Acess2 module (0x%08x != 0x%08x)",
72 Module, Module->Magic, MODULE_MAGIC
74 LEAVE('i', MODULE_ERR_BADMODULE);
75 return MODULE_ERR_BADMODULE;
77 LOG("Module->Name = %p \"%s\"", Module->Name, Module->Name);
79 if(Module->Arch != MODULE_ARCH_ID) {
82 "Module %p (%s) is for another architecture (%i)",
83 Module, Module->Name, Module->Arch
85 LEAVE('i', MODULE_ERR_BADMODULE);
86 return MODULE_ERR_BADMODULE;
89 LOG("Module->Flags = %x", Module->Flags);
90 if(Module->Flags & MODULE_FLAG_LOADERROR ) {
91 Log_Warning("Module", "%s has already attempted to load and encountered errors", Module->Name);
92 LEAVE('i', MODULE_ERR_MISC);
93 return MODULE_ERR_MISC;
96 deps = Module->Dependencies;
98 // Check if the module has been loaded
99 for( mod = gLoadedModules; mod; mod = mod->Next )
101 if(mod == Module) LEAVE_RET('i', 0);
104 // Add to the "loading" (prevents circular deps)
105 Module->Next = gLoadingModules;
106 gLoadingModules = Module;
108 // Scan dependency list
109 for( j = 0; deps && deps[j]; j++ )
111 // Check if the module is already loaded
112 for( mod = gLoadedModules; mod; mod = mod->Next )
114 if(strcmp(deps[j], mod->Name) == 0)
117 if( mod ) continue; // Dependency is loaded, check the rest
119 // Ok, check if it's loading
120 for( mod = gLoadingModules->Next; mod; mod = mod->Next )
122 if(strcmp(deps[j], mod->Name) == 0)
126 Log_Warning("Module", "Circular dependency detected (%s and %s)",
127 mod->Name, Module->Name);
131 // So, if it's not loaded, we better load it then
132 for( i = 0; i < giNumBuiltinModules; i ++ )
134 if( strcmp(deps[j], gapBuiltinModules[i]->Name) == 0 )
137 if( i == giNumBuiltinModules ) {
138 Log_Warning("Module", "Dependency '%s' for module '%s' failed",
139 deps[j], Module->Name);
143 // Dependency is not loaded, so load it
144 ret = Module_int_Initialise(
145 gapBuiltinModules[i],
146 gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL
150 // The only "ok" error is NOTNEEDED
151 if(ret != MODULE_ERR_NOTNEEDED)
156 // All Dependencies OK? Initialise
157 StartupPrint(Module->Name);
158 Log_Log("Module", "Starting %p '%s' v%i.%i",
159 Module, Module->Name,
160 Module->Version >> 8, Module->Version & 0xFF
164 args = str_split( ArgString, ',' );
168 ret = Module->Init(args);
172 // Remove from loading list
173 gLoadingModules = gLoadingModules->Next;
175 if( ret != MODULE_ERR_OK ) {
178 case MODULE_ERR_MISC:
179 Log_Warning("Module", "Unable to load, reason: Miscelanious");
181 case MODULE_ERR_NOTNEEDED:
182 // Log_Debug("Module", "Unable to load, reason: Module not needed");
184 case MODULE_ERR_MALLOC:
185 Log_Warning("Module", "Unable to load, reason: Error in malloc/realloc/calloc, probably not good");
188 Log_Warning("Module", "Unable to load reason - Unknown code %i", ret);
191 Module->Flags |= MODULE_FLAG_LOADERROR;
195 LOG("ret = %i", ret);
197 // Add to loaded list
198 SHORTLOCK( &glModuleSpinlock );
199 Module->Next = gLoadedModules;
200 gLoadedModules = Module;
201 SHORTREL( &glModuleSpinlock );
206 size_t Modules_int_PopulateBuiltins(tModule **Array)
209 for( tModule *module = &gKernelModules; module < (tModule*)&gKernelModulesEnd; )
211 if(module->Magic == MODULE_MAGIC) {
213 Array[count] = module;
219 module = (void*)( (tVAddr)module + 4 );
226 * \brief Scans the builtin modules and creates an array of them
228 void Modules_int_GetBuiltinArray(void)
230 if( !gapBuiltinModules )
233 giNumBuiltinModules = Modules_int_PopulateBuiltins(NULL);
236 gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) );
237 gapBuiltinModules = malloc( giNumBuiltinModules * sizeof(tModule*) );
240 Modules_int_PopulateBuiltins(gapBuiltinModules);
245 * \brief Initialises builtin modules
247 void Modules_LoadBuiltins(void)
249 Modules_int_GetBuiltinArray();
250 for( int i = 0; i < giNumBuiltinModules; i++ )
252 Module_int_Initialise(
253 gapBuiltinModules[i],
254 (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL)
258 if( gasBuiltinModuleArgs != NULL )
259 free(gasBuiltinModuleArgs);
263 * \brief Initialise a builtin module given it's name
265 * E.g. Used by VTerm to load an alternate video driver at runtime
267 int Modules_InitialiseBuiltin(const char *Name)
271 // Check if it's loaded
272 if( Module_IsLoaded(Name) )
275 if( !gapBuiltinModules )
276 Modules_int_GetBuiltinArray();
278 for( i = 0; i < giNumBuiltinModules; i++ )
280 if( strcmp(gapBuiltinModules[i]->Name, Name) == 0 ) {
281 return Module_int_Initialise(gapBuiltinModules[i],
282 (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL)
290 * \brief Sets the parameters for a builtin module
292 void Modules_SetBuiltinParams(const char *Name, char *ArgString)
296 if( gasBuiltinModuleArgs == NULL )
298 Modules_int_GetBuiltinArray();
301 // I hate expensive scans
302 for( i = 0; i < giNumBuiltinModules; i++ )
304 if(strcmp( gapBuiltinModules[i]->Name, Name ) == 0) {
305 gasBuiltinModuleArgs[i] = ArgString;
310 Log_Warning("Modules", "Unknown builtin kernel module '%s'", Name);
314 * \brief Registers a tModuleLoader with the kernel
315 * \param Loader Pointer to loader structure (must be persistent)
317 int Module_RegisterLoader(tModuleLoader *Loader)
319 if(!Loader) return 1;
321 Loader->Next = gModule_Loaders;
322 gModule_Loaders = Loader;
328 * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
329 * \brief Load a module from a memory location
331 int Module_LoadMem(void *Buffer, Uint Length, const char *ArgString)
333 char path[VFS_MEMPATH_SIZE];
335 VFS_GetMemPath(path, Buffer, Length);
337 return Module_LoadFile( path, ArgString ) == EOK;
341 * \fn int Module_LoadFile(const char *Path, const char *ArgString)
342 * \brief Load a module from a file
344 int Module_LoadFile(const char *Path, const char *ArgString)
348 tModuleLoader *loader = NULL;
351 base = Binary_LoadKernel(Path);
355 Log_Warning("Module", "Module_LoadFile - Unable to load '%s'", Path);
359 // TODO: I need a way of relocating the dependencies before everything else, so
360 // they can be resolved before any other link errors
361 if( !Binary_Relocate(base) ) {
362 Log_Warning("Module", "Relocation of module %s failed", Path);
367 // Check for Acess Driver
368 if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
370 for( loader = gModule_Loaders; loader; loader = loader->Next)
372 if( loader->Detector(base) )
376 // Unknown module type?, return error
379 Log_Warning("Module", "Module '%s' does not have a Module Info struct", Path);
386 if( loader->Loader(base) )
394 if( !Module_int_ResolveDeps(info) ) {
395 Log_Warning("Module", "Dependencies not met for '%s'", Path);
400 if( Module_int_Initialise(info, ArgString) )
411 * \fn int Module_int_ResolveDeps(tModule *Info)
412 * \brief Resolves the dependencies
414 * \note Currently does not resolve the dependencies, just checks them
416 int Module_int_ResolveDeps(tModule *Info)
418 const char **names = Info->Dependencies;
420 // Walk dependencies array
421 for( ; *names; names++ )
423 // Check if the module is loaded
424 if( !Module_IsLoaded(*names) ) {
425 Log_Warning("Module", "Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
433 * \fn int Module_IsLoaded(const char *Name)
434 * \brief Checks if a module is loaded
435 * \param Name Name of module to find
437 int Module_IsLoaded(const char *Name)
439 tModule *mod = gLoadedModules;
442 for( ; mod; mod = mod->Next )
444 // If found, return true
445 if(strcmp(mod->Name, Name) == 0)
448 // not found - return false
453 * \brief Load a module if needed
455 int Module_EnsureLoaded(const char *Name)
457 if( Module_IsLoaded(Name) )
460 if( Modules_InitialiseBuiltin(Name) == 0 )
463 // TODO: Load from a file?