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

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