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

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