X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fmodules.c;h=37f5418bcaa3587755b93b4f4552acfa94b34ef5;hb=bd8dc898108f10c0498f4dc5d0164a50b5ff2e5c;hp=93de973d0b6b56081872beba8876a152ca7900be;hpb=246ff98ae5b16ef0e19fe082a9c900e9169a1f7b;p=tpg%2Facess2.git diff --git a/Kernel/modules.c b/Kernel/modules.c index 93de973d..37f5418b 100644 --- a/Kernel/modules.c +++ b/Kernel/modules.c @@ -2,19 +2,24 @@ * Acess2 * - Module Loader */ +#define DEBUG 0 #include #include #define USE_EDI 0 -#define USE_UDI 1 +#define USE_UDI 0 // === PROTOTYPES === - int Modules_LoadBuiltins(); + int Modules_LoadBuiltins(void); + 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); +// === EXPORTS === +EXPORT(Module_RegisterLoader); + // === IMPORTS === #if USE_UDI extern int UDI_LoadDriver(void *Base); @@ -25,99 +30,158 @@ extern void gKernelModulesEnd; // === GLOBALS === int giNumBuiltinModules = 0; - int giModuleSpinlock = 0; +tSpinlock glModuleSpinlock; tModule *gLoadedModules = NULL; +tModuleLoader *gModule_Loaders = NULL; +tModule *gLoadingModules = NULL; // === CODE === -int Modules_LoadBuiltins() +/** + * \brief Initialises a module + * \param Module Pointer to the module header + * \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) { - int i, j, k; - int numToInit = 0; - Uint8 *baIsLoaded; + int i, j; + int ret; char **deps; + tModule *mod; - giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; - giNumBuiltinModules /= sizeof(tModule); + ENTER("pModule", Module); - baIsLoaded = calloc( giNumBuiltinModules, sizeof(*baIsLoaded) ); + deps = Module->Dependencies; - // Pass 1 - Are the dependencies compiled in? - for( i = 0; i < giNumBuiltinModules; i++ ) + // Check if the module has been loaded + for( mod = gLoadedModules; mod; mod = mod->Next ) { - deps = gKernelModules[i].Dependencies; - if(deps) - { - for( j = 0; deps[j]; j++ ) - { - for( k = 0; k < giNumBuiltinModules; k++ ) { - if(strcmp(deps[j], gKernelModules[k].Name) == 0) - break; - } - if(k == giNumBuiltinModules) { - Warning("Unable to find dependency '%s' for '%s' in kernel", - deps[j], gKernelModules[i].Name); - - baIsLoaded[i] = -1; // Don't Load - break; - } - } - } - numToInit ++; + if(mod == Module) LEAVE_RET('i', 0); } - // Pass 2 - Intialise - while(numToInit) + // Add to the "loading" (prevents circular deps) + Module->Next = gLoadingModules; + gLoadingModules = Module; + + // Scan dependency list + for( j = 0; deps && deps[j]; j++ ) { - for( i = 0; i < giNumBuiltinModules; i++ ) + // Check if the module is already loaded + for( mod = gLoadedModules; mod; mod = mod->Next ) { - if( baIsLoaded[i] ) continue; // Ignore already loaded modules + if(strcmp(deps[j], mod->Name) == 0) + break; + } + if( mod ) continue; // Dependency is loaded, check the rest - deps = gKernelModules[i].Dependencies; - - if( deps ) - { - for( j = 0; deps[j]; j++ ) - { - for( k = 0; k < giNumBuiltinModules; k++ ) { - if(strcmp(deps[j], gKernelModules[k].Name) == 0) - break; - } - // `k` is assumed to be less than `giNumBuiltinModules` - - // If a dependency failed, skip and mark as failed - if( baIsLoaded[k] == -1 ) { - baIsLoaded[i] = -1; - numToInit --; - break; - } - // If a dependency is not intialised, skip - if( !baIsLoaded[k] ) break; - } - // Check if we broke out - if( deps[j] ) continue; - } - - // All Dependencies OK? Initialise - StartupPrint(gKernelModules[i].Name); - Log("Initialising %p '%s' v%i.%i...", - &gKernelModules[i], - gKernelModules[i].Name, - gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF - ); - if( gKernelModules[i].Init(NULL) == 0 ) { - Log("Loading Failed, all modules that depend on this will also fail"); - baIsLoaded[i] = -1; - } - // Mark as loaded - else - baIsLoaded[i] = 1; - numToInit --; + // Ok, check if it's loading + for( mod = gLoadingModules->Next; mod; mod = mod->Next ) + { + if(strcmp(deps[j], mod->Name) == 0) + break; + } + if( mod ) { + Warning("[MOD ] Circular dependency detected"); + 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 ) + break; + } + if( i == giNumBuiltinModules ) { + Warning("[MOD ] Dependency '%s' for module '%s' failed"); + return -1; + } + + // Dependency is not loaded, so load it + ret = Module_int_Initialise( &gKernelModules[i] ); + if( ret ) + { + // The only "ok" error is NOTNEEDED + if(ret != MODULE_ERR_NOTNEEDED) + LEAVE_RET('i', -1); + } + } + + // All Dependencies OK? Initialise + StartupPrint(Module->Name); + Log("[MOD ] Initialising %p '%s' v%i.%i...", + Module, Module->Name, + Module->Version >> 8, Module->Version & 0xFF + ); + + ret = Module->Init(NULL); + if( ret != MODULE_ERR_OK ) { + switch(ret) + { + case MODULE_ERR_MISC: + Warning("[MOD ] Unable to load, reason: Miscelanious"); + break; + case MODULE_ERR_NOTNEEDED: + Warning("[MOD ] Unable to load, reason: Module not needed (probably hardware not found)"); + break; + case MODULE_ERR_MALLOC: + Warning("[MOD ] Unable to load, reason: Error in malloc/realloc/calloc, probably not good"); + break; + default: + Warning("[MOD ] Unable to load reason - Unknown code %i", ret); + break; + } + LEAVE_RET('i', ret); + return ret; + } + + // Remove from loading list + gLoadingModules = gLoadingModules->Next; + + // Add to loaded list + LOCK( &glModuleSpinlock ); + Module->Next = gLoadedModules; + gLoadedModules = Module; + RELEASE( &glModuleSpinlock ); + + LEAVE_RET('i', 0); +} + +/** + * \brief Initialises builtin modules + */ +int Modules_LoadBuiltins() +{ + int i; + + // Count modules + giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; + giNumBuiltinModules /= sizeof(tModule); + + for( i = 0; i < giNumBuiltinModules; i++ ) + { + Module_int_Initialise( &gKernelModules[i] ); } return 0; } +/** + * \brief Registers a tModuleLoader with the kernel + * \param Loader Pointer to loader structure (must be persistent) + */ +int Module_RegisterLoader(tModuleLoader *Loader) +{ + if(!Loader) return 1; + + Loader->Next = gModule_Loaders; + gModule_Loaders = Loader; + + return 0; +} + /** * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString) * \brief Load a module from a memory location @@ -152,23 +216,22 @@ int Module_LoadFile(char *Path, char *ArgString) // Check for Acess Driver if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 ) { + tModuleLoader *tmp; + for( tmp = gModule_Loaders; tmp; tmp = tmp->Next) + { + if( tmp->Detector(base) == 0 ) continue; + + return tmp->Loader(base); + } + #if USE_EDI // Check for EDI Driver if( Binary_FindSymbol(base, "driver_init", NULL ) != 0 ) { - Binary_Relocate(base); // Relocate return Module_InitEDI( base ); // And intialise } #endif - #if USE_UDI - if( Binary_FindSymbol(base, "udi_init_info", NULL ) != 0 ) - { - Binary_Relocate(base); // Relocate - return UDI_LoadDriver( base ); // And intialise - } - #endif - // Unknown module type?, return error Binary_Unload(base); #if USE_EDI @@ -193,6 +256,13 @@ int Module_LoadFile(char *Path, char *ArgString) return 0; } + #if 1 + if( Module_int_Initialise( info ) ) + { + Binary_Unload(base); + return 0; + } + #else // Resolve Dependencies if( !Module_int_ResolveDeps(info) ) { Binary_Unload(base); @@ -214,10 +284,11 @@ int Module_LoadFile(char *Path, char *ArgString) } // Add to list - LOCK( &giModuleSpinlock ); + LOCK( &glModuleSpinlock ); info->Next = gLoadedModules; gLoadedModules = info; - RELEASE( &giModuleSpinlock ); + RELEASE( &glModuleSpinlock ); + #endif return 1; }