93de973d0b6b56081872beba8876a152ca7900be
[tpg/acess2.git] / Kernel / modules.c
1 /*
2  * Acess2
3  * - Module Loader
4  */
5 #include <acess.h>
6 #include <modules.h>
7
8 #define USE_EDI 0
9 #define USE_UDI 1
10
11 // === PROTOTYPES ===
12  int    Modules_LoadBuiltins();
13  int    Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
14  int    Module_LoadFile(char *Path, char *ArgString);
15  int    Module_int_ResolveDeps(tModule *Info);
16  int    Module_IsLoaded(char *Name);
17
18 // === IMPORTS ===
19 #if USE_UDI
20 extern int      UDI_LoadDriver(void *Base);
21 #endif
22 extern void     StartupPrint(char *Str);
23 extern tModule  gKernelModules[];
24 extern void     gKernelModulesEnd;
25
26 // === GLOBALS ===
27  int    giNumBuiltinModules = 0;
28  int    giModuleSpinlock = 0;
29 tModule *gLoadedModules = NULL;
30
31 // === CODE ===
32 int Modules_LoadBuiltins()
33 {
34          int    i, j, k;
35          int    numToInit = 0;
36         Uint8   *baIsLoaded;
37         char    **deps;
38         
39         giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
40         giNumBuiltinModules /= sizeof(tModule);
41         
42         baIsLoaded = calloc( giNumBuiltinModules, sizeof(*baIsLoaded) );
43         
44         // Pass 1 - Are the dependencies compiled in?
45         for( i = 0; i < giNumBuiltinModules; i++ )
46         {
47                 deps = gKernelModules[i].Dependencies;
48                 if(deps)
49                 {
50                         for( j = 0; deps[j]; j++ )
51                         {
52                                 for( k = 0; k < giNumBuiltinModules; k++ ) {
53                                         if(strcmp(deps[j], gKernelModules[k].Name) == 0)
54                                                 break;
55                                 }
56                                 if(k == giNumBuiltinModules) {
57                                         Warning("Unable to find dependency '%s' for '%s' in kernel",
58                                                 deps[j], gKernelModules[i].Name);
59                                         
60                                         baIsLoaded[i] = -1;     // Don't Load
61                                         break;
62                                 }
63                         }
64                 }
65                 numToInit ++;
66         }
67         
68         // Pass 2 - Intialise
69         while(numToInit)
70         {
71                 for( i = 0; i < giNumBuiltinModules; i++ )
72                 {
73                         if( baIsLoaded[i] )     continue;       // Ignore already loaded modules
74                 
75                         deps = gKernelModules[i].Dependencies;
76                         
77                         if( deps )
78                         {
79                                 for( j = 0; deps[j]; j++ )
80                                 {
81                                         for( k = 0; k < giNumBuiltinModules; k++ ) {
82                                                 if(strcmp(deps[j], gKernelModules[k].Name) == 0)
83                                                         break;
84                                         }
85                                         // `k` is assumed to be less than `giNumBuiltinModules`
86                                         
87                                         // If a dependency failed, skip and mark as failed
88                                         if( baIsLoaded[k] == -1 ) {
89                                                 baIsLoaded[i] = -1;
90                                                 numToInit --;
91                                                 break;
92                                         }
93                                         // If a dependency is not intialised, skip
94                                         if( !baIsLoaded[k] )    break;
95                                 }
96                                 // Check if we broke out
97                                 if( deps[j] )   continue;
98                         }
99                         
100                         // All Dependencies OK? Initialise
101                         StartupPrint(gKernelModules[i].Name);
102                         Log("Initialising %p '%s' v%i.%i...",
103                                 &gKernelModules[i],
104                                 gKernelModules[i].Name,
105                                 gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF
106                                 );
107                         if( gKernelModules[i].Init(NULL) == 0 ) {
108                                 Log("Loading Failed, all modules that depend on this will also fail");
109                                 baIsLoaded[i] = -1;
110                         }
111                         // Mark as loaded
112                         else
113                                 baIsLoaded[i] = 1;
114                         numToInit --;
115                 }
116         }
117         
118         return 0;
119 }
120
121 /**
122  * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
123  * \brief Load a module from a memory location
124  */
125 int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
126 {
127         char    path[VFS_MEMPATH_SIZE];
128         
129         VFS_GetMemPath(path, Buffer, Length);
130         
131         return Module_LoadFile( path, ArgString );
132 }
133
134 /**
135  * \fn int Module_LoadFile(char *Path, char *ArgString)
136  * \brief Load a module from a file
137  */
138 int Module_LoadFile(char *Path, char *ArgString)
139 {
140         void    *base;
141         tModule *info;
142         
143         // Load Binary
144         base = Binary_LoadKernel(Path);
145         
146         // Error check
147         if(base == NULL) {
148                 Warning("Module_LoadFile: Unable to load '%s'", Path);
149                 return 0;
150         }
151         
152         // Check for Acess Driver
153         if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
154         {
155                 #if USE_EDI
156                 // Check for EDI Driver
157                 if( Binary_FindSymbol(base, "driver_init", NULL ) != 0 )
158                 {
159                         Binary_Relocate(base);  // Relocate
160                         return Module_InitEDI( base );  // And intialise
161                 }
162                 #endif
163                 
164                 #if USE_UDI
165                 if( Binary_FindSymbol(base, "udi_init_info", NULL ) != 0 )
166                 {
167                         Binary_Relocate(base);  // Relocate
168                         return UDI_LoadDriver( base );  // And intialise
169                 }
170                 #endif
171                 
172                 // Unknown module type?, return error
173                 Binary_Unload(base);
174                 #if USE_EDI
175                 Warning("Module_LoadFile: Module has neither a Module Info struct, nor an EDI entrypoint");
176                 #else
177                 Warning("Module_LoadFile: Module does not have a Module Info struct");
178                 #endif
179                 return 0;
180         }
181         
182         // Check magic number
183         if(info->Magic != MODULE_MAGIC)
184         {
185                 Warning("Module_LoadFile: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
186                 return 0;
187         }
188         
189         // Check Architecture
190         if(info->Arch != MODULE_ARCH_ID)
191         {
192                 Warning("Module_LoadFile: Module is for a different architecture");
193                 return 0;
194         }
195         
196         // Resolve Dependencies
197         if( !Module_int_ResolveDeps(info) ) {
198                 Binary_Unload(base);
199                 return 0;
200         }
201         
202         Log("Initialising %p '%s' v%i.%i...",
203                                 info,
204                                 info->Name,
205                                 info->Version>>8, info->Version & 0xFF
206                                 );
207         
208         // Call Initialiser
209         //if( info->Init( ArgString ) != 0 )
210         if( info->Init( NULL ) == 0 )
211         {
212                 Binary_Unload(base);
213                 return 0;
214         }
215         
216         // Add to list
217         LOCK( &giModuleSpinlock );
218         info->Next = gLoadedModules;
219         gLoadedModules = info;
220         RELEASE( &giModuleSpinlock );
221         
222         return 1;
223 }
224
225 /**
226  * \fn int Module_int_ResolveDeps(tModule *Info)
227  * \brief Resolves the dependencies
228  * \todo Implement
229  * \note Currently does not resolve the dependencies, just checks them
230  */
231 int Module_int_ResolveDeps(tModule *Info)
232 {
233         char    **names = Info->Dependencies;
234         
235         // Walk dependencies array
236         for( ; *names; names++ )
237         {
238                 // Check if the module is loaded
239                 if( !Module_IsLoaded(*names) ) {
240                         Warning("Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
241                         return 0;
242                 }
243         }
244         return 1;
245 }
246
247 /**
248  * \fn int Module_IsLoaded(char *Name)
249  * \brief Checks if a module is loaded
250  * \param Name  Name of module to find
251  */
252 int Module_IsLoaded(char *Name)
253 {
254         tModule *mod = gLoadedModules;
255         
256         // Scan loaded list
257         for( ; mod; mod = mod->Next )
258         {
259                 // If found, return true
260                 if(strcmp(mod->Name, Name) == 0)
261                         return 1;
262         }
263         // not found - return false
264         return 0;
265 }

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