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

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