Initial commit of kernel only
[tpg/acess2.git] / Kernel / modules.c
1 /*
2  * Acess2
3  * - Module Loader
4  */
5 #include <common.h>
6 #include <modules.h>
7
8 // === PROTOTYPES ===
9  int    Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
10  int    Module_LoadFile(char *Path, char *ArgString);
11  int    Module_int_ResolveDeps(tModule *Info);
12  int    Module_IsLoaded(char *Name);
13
14 // === IMPORTS ===
15 extern tModule  gKernelModules[];
16 extern void             gKernelModulesEnd;
17
18 // === GLOBALS ===
19  int    giNumBuiltinModules = 0;
20  int    giModuleSpinlock = 0;
21 tModule *gLoadedModules = NULL;
22
23 // === CODE ===
24 int Modules_LoadBuiltins()
25 {
26          int    i;
27         giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
28         giNumBuiltinModules /= sizeof(tModule);
29         
30         for( i = 0; i < giNumBuiltinModules; i++ )
31         {
32                 Log("Initialising %p '%s' v%i.%i...",
33                         &gKernelModules[i],
34                         gKernelModules[i].Name,
35                         gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF
36                         );
37                 gKernelModules[i].Init(NULL);
38         }
39         
40         return 0;
41 }
42
43 /**
44  * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
45  * \brief Load a module from a memory location
46  */
47 int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
48 {
49         char    path[VFS_MEMPATH_SIZE];
50         
51         VFS_GetMemPath(Buffer, Length, path);
52         
53         return Module_LoadFile( path, ArgString );
54 }
55
56 /**
57  * \fn int Module_LoadFile(char *Path, char *ArgString)
58  * \brief Load a module from a file
59  */
60 int Module_LoadFile(char *Path, char *ArgString)
61 {
62         void    *base;
63         tModule *info;
64         
65         // Load Binary
66         base = Binary_LoadKernel(Path);
67         
68         // Error check
69         if(base == NULL)        return 0;
70         
71         // Check for Acess Driver
72         if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
73         {
74                 #if USE_EDI
75                 // Check for EDI Driver
76                 if( Binary_FindSymbol(base, "driver_init", NULL ) == 0 )
77                 {
78                         Binary_Relocate(base);  // Relocate
79                         return Module_InitEDI( base );  // And intialise
80                 }
81                 #endif
82                 
83                 // Unknown module type?, return error
84                 Binary_Unload(base);
85                 #if USE_EDI
86                 Warning("Module_LoadMem: Module has neither a Module Info struct, nor an EDI entrypoint");
87                 #else
88                 Warning("Module_LoadMem: Module does not have a Module Info struct");
89                 #endif
90                 return 0;
91         }
92         
93         LOG("info = %p\n", info);
94         Debug_HexDump("info", info, 6*4);
95         
96         // Check magic number
97         if(info->Magic != MODULE_MAGIC)
98         {
99                 Warning("Module_LoadMem: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
100                 return 0;
101         }
102         
103         // Check Architecture
104         if(info->Arch != MODULE_ARCH_ID)
105         {
106                 Warning("Module_LoadMem: Module is for a different architecture");
107                 return 0;
108         }
109         
110         // Resolve Dependencies
111         if( !Module_int_ResolveDeps(info) ) {
112                 Binary_Unload(base);
113                 return 0;
114         }
115         
116         // Call Initialiser
117         //if( info->Init( ArgString ) != 0 )
118         if( info->Init( NULL ) == 0 )
119         {
120                 Binary_Unload(base);
121                 return 0;
122         }
123         
124         // Add to list
125         LOCK( &giModuleSpinlock );
126         info->Next = gLoadedModules;
127         gLoadedModules = info;
128         RELEASE( &giModuleSpinlock );
129         
130         return 1;
131 }
132
133 /**
134  * \fn int Module_int_ResolveDeps(tModule *Info)
135  * \brief Resolves the dependencies
136  * \todo Implement
137  * \note Currently does not resolve the dependencies, just checks them
138  */
139 int Module_int_ResolveDeps(tModule *Info)
140 {
141         char    **names = Info->Dependencies;
142         
143         // Walk dependencies array
144         for( ; *names; names++ )
145         {
146                 // Check if the module is loaded
147                 if( !Module_IsLoaded(*names) ) {
148                         Warning("Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
149                         return 0;
150                 }
151         }
152         return 1;
153 }
154
155 /**
156  * \fn int Module_IsLoaded(char *Name)
157  * \brief Checks if a module is loaded
158  * \param Name  Name of module to find
159  */
160 int Module_IsLoaded(char *Name)
161 {
162         tModule *mod = gLoadedModules;
163         
164         // Scan loaded list
165         for( ; mod; mod = mod->Next )
166         {
167                 // If found, return true
168                 if(strcmp(mod->Name, Name) == 0)
169                         return 1;
170         }
171         // not found - return false
172         return 0;
173 }

UCC git Repository :: git.ucc.asn.au