X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fmodules.c;h=c0c021615a329b0aa09f148d96448e0cdd5d3d0e;hb=7e5607004c3221d55c7992148b2f0d958cf28533;hp=41fb51438863a304b362a1acdf2e0e613d86941e;hpb=85eb17b306404571aa39596946c87ad9bb1d9d13;p=tpg%2Facess2.git diff --git a/Kernel/modules.c b/Kernel/modules.c index 41fb5143..c0c02161 100644 --- a/Kernel/modules.c +++ b/Kernel/modules.c @@ -10,14 +10,17 @@ #define USE_UDI 0 // === PROTOTYPES === - int Module_int_Initialise(tModule *Module, char *ArgString); + int Module_int_Initialise(tModule *Module, const char *ArgString); +void Modules_int_GetBuiltinArray(void); void Modules_LoadBuiltins(void); -void Modules_SetBuiltinParams(char *Name, char *ArgString); - int Module_RegisterLoader(tModuleLoader *Loader); - int Module_LoadMem(void *Buffer, Uint Length, char *ArgString); - int Module_LoadFile(char *Path, char *ArgString); +void Modules_SetBuiltinParams(const char *Name, char *ArgString); + int Modules_InitialiseBuiltin(const char *Name); +// int Module_RegisterLoader(tModuleLoader *Loader); +// int Module_LoadMem(void *Buffer, Uint Length, char *ArgString); +// int Module_LoadFile(char *Path, char *ArgString); int Module_int_ResolveDeps(tModule *Info); - int Module_IsLoaded(char *Name); + int Module_IsLoaded(const char *Name); +// int Module_EnsureLoaded(const char *Name); // === EXPORTS === EXPORT(Module_RegisterLoader); @@ -26,37 +29,58 @@ EXPORT(Module_RegisterLoader); #if USE_UDI extern int UDI_LoadDriver(void *Base); #endif -extern void StartupPrint(char *Str); -extern tModule gKernelModules[]; -extern void gKernelModulesEnd; +extern void StartupPrint(const char *Str); +extern tModule gKernelModules; +extern tModule gKernelModulesEnd; // === GLOBALS === int giNumBuiltinModules = 0; -tSpinlock glModuleSpinlock; +tShortSpinlock glModuleSpinlock; tModule *gLoadedModules = NULL; tModuleLoader *gModule_Loaders = NULL; tModule *gLoadingModules = NULL; +tModule **gapBuiltinModules = NULL; char **gasBuiltinModuleArgs; // === CODE === /** * \brief Initialises a module * \param Module Pointer to the module header + * \param ArgString Comma separated list of module arguments * \return Zero on success, eModuleErrors or -1 on error * \retval -1 Returned if a dependency fails, or a circular dependency * exists. * \retval 0 Returned on success * \retval >0 Error code form the module's initialisation function */ -int Module_int_Initialise(tModule *Module, char *ArgString) +int Module_int_Initialise(tModule *Module, const char *ArgString) { int i, j; int ret; - char **deps; + const char **deps; char **args; tModule *mod; ENTER("pModule", Module); + LOG("Module->Magic = 0x%x", Module->Magic); + if(Module->Magic != MODULE_MAGIC) { + Log_Warning( + "Module", + "Module %p is no a valid Acess2 module (0x%08x != 0x%08x)", + Module, Module->Magic, MODULE_MAGIC + ); + LEAVE('i', MODULE_ERR_BADMODULE); + return MODULE_ERR_BADMODULE; + } + LOG("Module->Name = %p \"%s\"", Module->Name, Module->Name); + + if(Module->Arch != MODULE_ARCH_ID) { + Log_Warning( + "Module", + "Module %p (%s) is for another architecture (%i)", + Module, Module->Name, Module->Arch + ); + } deps = Module->Dependencies; @@ -88,24 +112,26 @@ int Module_int_Initialise(tModule *Module, char *ArgString) break; } if( mod ) { - Log_Warning("Module", "Circular dependency detected"); + Log_Warning("Module", "Circular dependency detected (%s and %s)", + mod->Name, Module->Name); LEAVE_RET('i', -1); } // So, if it's not loaded, we better load it then for( i = 0; i < giNumBuiltinModules; i ++ ) { - if( strcmp(deps[j], gKernelModules[i].Name) == 0 ) + if( strcmp(deps[j], gapBuiltinModules[i]->Name) == 0 ) break; } if( i == giNumBuiltinModules ) { - Log_Warning("Module", "Dependency '%s' for module '%s' failed"); + Log_Warning("Module", "Dependency '%s' for module '%s' failed", + deps[j], Module->Name); return -1; } // Dependency is not loaded, so load it ret = Module_int_Initialise( - &gKernelModules[i], + gapBuiltinModules[i], gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL ); if( ret ) @@ -118,7 +144,7 @@ int Module_int_Initialise(tModule *Module, char *ArgString) // All Dependencies OK? Initialise StartupPrint(Module->Name); - Log_Log("Module", "Initialising %p '%s' v%i.%i...", + Log_Log("Module", "Starting %p '%s' v%i.%i", Module, Module->Name, Module->Version >> 8, Module->Version & 0xFF ); @@ -132,6 +158,9 @@ int Module_int_Initialise(tModule *Module, char *ArgString) if(args) free(args); + // Remove from loading list + gLoadingModules = gLoadingModules->Next; + if( ret != MODULE_ERR_OK ) { switch(ret) { @@ -153,18 +182,57 @@ int Module_int_Initialise(tModule *Module, char *ArgString) } LOG("ret = %i", ret); - // Remove from loading list - gLoadingModules = gLoadingModules->Next; - // Add to loaded list - LOCK( &glModuleSpinlock ); + SHORTLOCK( &glModuleSpinlock ); Module->Next = gLoadedModules; gLoadedModules = Module; - RELEASE( &glModuleSpinlock ); + SHORTREL( &glModuleSpinlock ); LEAVE_RET('i', 0); } +/** + * \brief Scans the builtin modules and creates an array of them + */ +void Modules_int_GetBuiltinArray(void) +{ + int i; + tModule *module; + + // Count + module = &gKernelModules; + i = 0; + while( (tVAddr)module < (tVAddr)&gKernelModulesEnd ) + { + if(module->Magic == MODULE_MAGIC) { + i ++; + module ++; + } + else + module = (void*)( (tVAddr)module + 4 ); + } + + // Create + giNumBuiltinModules = i; + gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) ); + gapBuiltinModules = malloc( giNumBuiltinModules * sizeof(tModule*) ); + + + // Fill + module = &gKernelModules; + i = 0; + while( (tVAddr)module < (tVAddr)&gKernelModulesEnd ) + { + if(module->Magic == MODULE_MAGIC) { + gapBuiltinModules[i] = module; + i ++; + module ++; + } + else + module = (void*)( (tVAddr)module + 4 ); + } +} + /** * \brief Initialises builtin modules */ @@ -172,14 +240,13 @@ void Modules_LoadBuiltins() { int i; - // Count modules - giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; - giNumBuiltinModules /= sizeof(tModule); + if( !gapBuiltinModules ) + Modules_int_GetBuiltinArray(); for( i = 0; i < giNumBuiltinModules; i++ ) { Module_int_Initialise( - &gKernelModules[i], + gapBuiltinModules[i], (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL) ); } @@ -188,21 +255,49 @@ void Modules_LoadBuiltins() free(gasBuiltinModuleArgs); } +/** + * \brief Initialise a builtin module given it's name + * + * E.g. Used by VTerm to load an alternate video driver at runtime + */ +int Modules_InitialiseBuiltin(const char *Name) +{ + int i; + + // Check if it's loaded + if( Module_IsLoaded(Name) ) + return 0; + + if( !gapBuiltinModules ) + Modules_int_GetBuiltinArray(); + + for( i = 0; i < giNumBuiltinModules; i++ ) + { + if( strcmp(gapBuiltinModules[i]->Name, Name) == 0 ) { + return Module_int_Initialise(gapBuiltinModules[i], + (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL) + ); + } + } + return -1; +} + /** * \brief Sets the parameters for a builtin module */ -void Modules_SetBuiltinParams(char *Name, char *ArgString) +void Modules_SetBuiltinParams(const char *Name, char *ArgString) { int i; - if( gasBuiltinModuleArgs == NULL ) { - giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; - giNumBuiltinModules /= sizeof(tModule); - gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) ); + + if( gasBuiltinModuleArgs == NULL ) + { + Modules_int_GetBuiltinArray(); } - for( i = 0; i < giNumBuiltinModules; i ++ ) + // I hate expensive scans + for( i = 0; i < giNumBuiltinModules; i++ ) { - if(strcmp( gKernelModules[i].Name, Name ) == 0) { + if(strcmp( gapBuiltinModules[i]->Name, Name ) == 0) { gasBuiltinModuleArgs[i] = ArgString; return ; } @@ -229,7 +324,7 @@ int Module_RegisterLoader(tModuleLoader *Loader) * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString) * \brief Load a module from a memory location */ -int Module_LoadMem(void *Buffer, Uint Length, char *ArgString) +int Module_LoadMem(void *Buffer, Uint Length, const char *ArgString) { char path[VFS_MEMPATH_SIZE]; @@ -239,10 +334,10 @@ int Module_LoadMem(void *Buffer, Uint Length, char *ArgString) } /** - * \fn int Module_LoadFile(char *Path, char *ArgString) + * \fn int Module_LoadFile(const char *Path, const char *ArgString) * \brief Load a module from a file */ -int Module_LoadFile(char *Path, char *ArgString) +int Module_LoadFile(const char *Path, const char *ArgString) { void *base; tModule *info; @@ -285,53 +380,12 @@ int Module_LoadFile(char *Path, char *ArgString) return 0; } - // Check magic number - if(info->Magic != MODULE_MAGIC) - { - Log_Warning("Module", "Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC); - return 0; - } - - // Check Architecture - if(info->Arch != MODULE_ARCH_ID) - { - Log_Warning("Module", "Module is for a different architecture"); - return 0; - } - - #if 1 + // Initialise (and register) if( Module_int_Initialise( info, ArgString ) ) { Binary_Unload(base); return 0; } - #else - // Resolve Dependencies - if( !Module_int_ResolveDeps(info) ) { - Binary_Unload(base); - return 0; - } - - Log_Log("Module", "Initialising %p '%s' v%i.%i...", - info, - info->Name, - info->Version>>8, info->Version & 0xFF - ); - - // Call Initialiser - //if( info->Init( ArgString ) != 0 ) - if( info->Init( NULL ) == 0 ) - { - Binary_Unload(base); - return 0; - } - - // Add to list - LOCK( &glModuleSpinlock ); - info->Next = gLoadedModules; - gLoadedModules = info; - RELEASE( &glModuleSpinlock ); - #endif return 1; } @@ -344,7 +398,7 @@ int Module_LoadFile(char *Path, char *ArgString) */ int Module_int_ResolveDeps(tModule *Info) { - char **names = Info->Dependencies; + const char **names = Info->Dependencies; // Walk dependencies array for( ; *names; names++ ) @@ -359,11 +413,11 @@ int Module_int_ResolveDeps(tModule *Info) } /** - * \fn int Module_IsLoaded(char *Name) + * \fn int Module_IsLoaded(const char *Name) * \brief Checks if a module is loaded * \param Name Name of module to find */ -int Module_IsLoaded(char *Name) +int Module_IsLoaded(const char *Name) { tModule *mod = gLoadedModules; @@ -377,3 +431,19 @@ int Module_IsLoaded(char *Name) // not found - return false return 0; } + +/** + * \brief Load a module if needed + */ +int Module_EnsureLoaded(const char *Name) +{ + if( Module_IsLoaded(Name) ) + return 0; + + if( Modules_InitialiseBuiltin(Name) == 0 ) + return 0; + + // TODO: Load from a file? + + return -1; +}