Altered keyboard driver to correctly support Unicode
[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                         gKernelModules[i].Init(NULL);
102                         // Mark as loaded
103                         baIsLoaded[i] = 1;
104                         numToInit --;
105                 }
106         }
107         
108         return 0;
109 }
110
111 /**
112  * \fn int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
113  * \brief Load a module from a memory location
114  */
115 int Module_LoadMem(void *Buffer, Uint Length, char *ArgString)
116 {
117         char    path[VFS_MEMPATH_SIZE];
118         
119         VFS_GetMemPath(Buffer, Length, path);
120         
121         return Module_LoadFile( path, ArgString );
122 }
123
124 /**
125  * \fn int Module_LoadFile(char *Path, char *ArgString)
126  * \brief Load a module from a file
127  */
128 int Module_LoadFile(char *Path, char *ArgString)
129 {
130         void    *base;
131         tModule *info;
132         
133         // Load Binary
134         base = Binary_LoadKernel(Path);
135         
136         // Error check
137         if(base == NULL)        return 0;
138         
139         // Check for Acess Driver
140         if( Binary_FindSymbol(base, "DriverInfo", (Uint*)&info ) == 0 )
141         {
142                 #if USE_EDI
143                 // Check for EDI Driver
144                 if( Binary_FindSymbol(base, "driver_init", NULL ) == 0 )
145                 {
146                         Binary_Relocate(base);  // Relocate
147                         return Module_InitEDI( base );  // And intialise
148                 }
149                 #endif
150                 
151                 // Unknown module type?, return error
152                 Binary_Unload(base);
153                 #if USE_EDI
154                 Warning("Module_LoadMem: Module has neither a Module Info struct, nor an EDI entrypoint");
155                 #else
156                 Warning("Module_LoadMem: Module does not have a Module Info struct");
157                 #endif
158                 return 0;
159         }
160         
161         // Check magic number
162         if(info->Magic != MODULE_MAGIC)
163         {
164                 Warning("Module_LoadMem: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
165                 return 0;
166         }
167         
168         // Check Architecture
169         if(info->Arch != MODULE_ARCH_ID)
170         {
171                 Warning("Module_LoadMem: Module is for a different architecture");
172                 return 0;
173         }
174         
175         // Resolve Dependencies
176         if( !Module_int_ResolveDeps(info) ) {
177                 Binary_Unload(base);
178                 return 0;
179         }
180         
181         Log("Initialising %p '%s' v%i.%i...",
182                                 info,
183                                 info->Name,
184                                 info->Version>>8, info->Version & 0xFF
185                                 );
186         
187         // Call Initialiser
188         //if( info->Init( ArgString ) != 0 )
189         if( info->Init( NULL ) == 0 )
190         {
191                 Binary_Unload(base);
192                 return 0;
193         }
194         
195         // Add to list
196         LOCK( &giModuleSpinlock );
197         info->Next = gLoadedModules;
198         gLoadedModules = info;
199         RELEASE( &giModuleSpinlock );
200         
201         return 1;
202 }
203
204 /**
205  * \fn int Module_int_ResolveDeps(tModule *Info)
206  * \brief Resolves the dependencies
207  * \todo Implement
208  * \note Currently does not resolve the dependencies, just checks them
209  */
210 int Module_int_ResolveDeps(tModule *Info)
211 {
212         char    **names = Info->Dependencies;
213         
214         // Walk dependencies array
215         for( ; *names; names++ )
216         {
217                 // Check if the module is loaded
218                 if( !Module_IsLoaded(*names) ) {
219                         Warning("Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
220                         return 0;
221                 }
222         }
223         return 1;
224 }
225
226 /**
227  * \fn int Module_IsLoaded(char *Name)
228  * \brief Checks if a module is loaded
229  * \param Name  Name of module to find
230  */
231 int Module_IsLoaded(char *Name)
232 {
233         tModule *mod = gLoadedModules;
234         
235         // Scan loaded list
236         for( ; mod; mod = mod->Next )
237         {
238                 // If found, return true
239                 if(strcmp(mod->Name, Name) == 0)
240                         return 1;
241         }
242         // not found - return false
243         return 0;
244 }

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