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

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