X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fmodules.c;h=e4f49b288e776b2b854bb771ad09ee3c5d92e213;hb=1c2a87ec67d332b6a165c79398693eac1eb1166e;hp=b7209fff379a0ce706562dd706dd934d4445d06f;hpb=8fef00cfab98773a519ab909fa9da9dc7af692db;p=tpg%2Facess2.git diff --git a/Kernel/modules.c b/Kernel/modules.c index b7209fff..e4f49b28 100644 --- a/Kernel/modules.c +++ b/Kernel/modules.c @@ -2,44 +2,137 @@ * Acess2 * - Module Loader */ -#include +#include #include +#define USE_EDI 0 +#define USE_UDI 1 + // === PROTOTYPES === + int Modules_LoadBuiltins(); 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); // === IMPORTS === +#if USE_UDI +extern int UDI_LoadDriver(void *Base); +#endif +extern void StartupPrint(char *Str); extern tModule gKernelModules[]; -extern void gKernelModulesEnd; +extern void gKernelModulesEnd; // === GLOBALS === int giNumBuiltinModules = 0; int giModuleSpinlock = 0; tModule *gLoadedModules = NULL; +tModuleLoader *gModule_Loaders = NULL; // === CODE === int Modules_LoadBuiltins() { - int i; + int i, j, k; + int numToInit = 0; + Uint8 *baIsLoaded; + char **deps; + giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; giNumBuiltinModules /= sizeof(tModule); + baIsLoaded = calloc( giNumBuiltinModules, sizeof(*baIsLoaded) ); + + // Pass 1 - Are the dependencies compiled in? for( i = 0; i < giNumBuiltinModules; i++ ) { - Log("Initialising %p '%s' v%i.%i...", - &gKernelModules[i], - gKernelModules[i].Name, - gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF - ); - gKernelModules[i].Init(NULL); + 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 ++; + } + + // Pass 2 - Intialise + while(numToInit) + { + for( i = 0; i < giNumBuiltinModules; i++ ) + { + if( baIsLoaded[i] ) continue; // Ignore already loaded modules + + 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 --; + } } 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 @@ -48,7 +141,7 @@ int Module_LoadMem(void *Buffer, Uint Length, char *ArgString) { char path[VFS_MEMPATH_SIZE]; - VFS_GetMemPath(Buffer, Length, path); + VFS_GetMemPath(path, Buffer, Length); return Module_LoadFile( path, ArgString ); } @@ -66,16 +159,26 @@ int Module_LoadFile(char *Path, char *ArgString) base = Binary_LoadKernel(Path); // Error check - if(base == NULL) return 0; + if(base == NULL) { + Warning("Module_LoadFile: Unable to load '%s'", Path); + return 0; + } // 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 ) + if( Binary_FindSymbol(base, "driver_init", NULL ) != 0 ) { - Binary_Relocate(base); // Relocate return Module_InitEDI( base ); // And intialise } #endif @@ -83,9 +186,9 @@ int Module_LoadFile(char *Path, char *ArgString) // Unknown module type?, return error Binary_Unload(base); #if USE_EDI - Warning("Module_LoadMem: Module has neither a Module Info struct, nor an EDI entrypoint"); + Warning("Module_LoadFile: Module has neither a Module Info struct, nor an EDI entrypoint"); #else - Warning("Module_LoadMem: Module does not have a Module Info struct"); + Warning("Module_LoadFile: Module does not have a Module Info struct"); #endif return 0; } @@ -93,14 +196,14 @@ int Module_LoadFile(char *Path, char *ArgString) // Check magic number if(info->Magic != MODULE_MAGIC) { - Warning("Module_LoadMem: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC); + Warning("Module_LoadFile: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC); return 0; } // Check Architecture if(info->Arch != MODULE_ARCH_ID) { - Warning("Module_LoadMem: Module is for a different architecture"); + Warning("Module_LoadFile: Module is for a different architecture"); return 0; } @@ -110,6 +213,12 @@ int Module_LoadFile(char *Path, char *ArgString) return 0; } + Log("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 )