Chameleon

Chameleon Svn Source Tree

Root/branches/xZen/src/modules/ModuleSystem/modules.c

Source at commit 1247 created 12 years 8 months ago.
By meklort, Update makefiles... initial work for fat modules
1/*
2 * Copyright 2010 Evan Lojewski. All rights reserved.
3 *
4 */
5#ifdef CONFIG_MODULESYSTEM_MODULE
6#ifndef CONFIG_MODULE_DEBUG
7#define CONFIG_MODULE_DEBUG 0
8#endif
9
10#include "boot.h"
11#include "modules.h"
12//#include <vers.h>
13
14extern void start_built_in_modules();
15
16#if CONFIG_MODULE_DEBUG
17#define DBG(x...)printf(x);
18#define DBGPAUSE()getchar()
19#else
20#define DBG(x...)
21#define DBGPAUSE()
22#endif
23
24// NOTE: Global so that modules can link with this
25UInt64 textAddress = 0;
26UInt64 textSection = 0;
27
28void* symbols_module_start = (void*)0xFFFFFFFF;// Global, value is populated by the makefile with actual address
29
30/** Internal symbols, however there are accessor methods **/
31moduleHook_t* moduleCallbacks = NULL;
32moduleList_t* loadedModules = NULL;
33symbolList_t* moduleSymbols = NULL;
34unsigned int (*lookup_symbol)(const char*) = NULL;
35
36
37/*
38 * Initialize the module system by loading the Symbols.dylib module.
39 * Once loaded, locate the _lookup_symbol function so that internal
40 * symbols can be resolved.
41 */
42int init_module_system()
43{
44 // Start any modules that were compiled in first.
45 start_built_in_modules();
46
47
48int retVal = 0;
49void (*module_start)(void) = NULL;
50char* module_data = symbols_module_start + BOOT2_ADDR;
51
52// Intialize module system
53if(symbols_module_start != (void*)0xFFFFFFFF)
54{
55// Module system was compiled in (Symbols.dylib addr known)
56module_start = parse_mach(module_data, &load_module, &add_symbol, NULL);
57
58if(module_start && module_start != (void*)0xFFFFFFFF)
59{
60// Notify the system that it was laoded
61module_loaded(SYMBOLS_MODULE, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT);
62
63(*module_start)();// Start the module. This will point to load_all_modules due to the way the dylib was constructed.
64execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL);
65DBG("Module %s Loaded.\n", SYMBOLS_MODULE);
66retVal = 1;
67
68}
69else
70{
71 module_data -= 0x10; // XCODE 4 HACK
72 module_start = parse_mach(module_data, &load_module, &add_symbol, NULL);
73
74 if(module_start && module_start != (void*)0xFFFFFFFF)
75 {
76 // Notify the system that it was laoded
77 module_loaded(SYMBOLS_MODULE, SYMBOLS_AUTHOR, SYMBOLS_DESCRIPTION, SYMBOLS_VERSION, SYMBOLS_COMPAT);
78
79 (*module_start)();// Start the module. This will point to load_all_modules due to the way the dylib was constructed.
80 execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL);
81 DBG("Module %s Loaded.\n", SYMBOLS_MODULE);
82 retVal = 1;
83
84 }
85 else
86 {
87 // The module does not have a valid start function
88 printf("Unable to start %s\n", SYMBOLS_MODULE); getchar();
89 }
90}
91}
92return retVal;
93}
94
95void start_built_in_module(const char* name,
96 const char* author,
97 const char* description,
98 UInt32 version,
99 UInt32 compat,
100 void(*start_function)(void))
101{
102 start_function();
103 // Notify the module system that this module really exists, specificaly, let other module link with it
104 module_loaded(name, author, description, version, compat);
105}
106
107
108/*
109 * Load all modules in the /Extra/modules/ directory
110 * Module depencdies will be loaded first
111 * Modules will only be loaded once. When loaded a module must
112 * setup apropriete function calls and hooks as required.
113 * NOTE: To ensure a module loads after another you may
114 * link one module with the other. For dyld to allow this, you must
115 * reference at least one symbol within the module.
116 */
117void load_all_modules()
118{
119char* name;
120long flags;
121long time;
122struct dirstuff* moduleDir = opendir("/Extra/modules/");
123while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
124{
125if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)
126{
127char* tmp = malloc(strlen(name) + 1);
128strcpy(tmp, name);
129
130if(!load_module(tmp))
131{
132// failed to load
133// free(tmp);
134}
135}
136else
137{
138DBG("Ignoring %s\n", name);
139}
140
141}
142}
143
144
145/*
146 * Load a module file in /Extra/modules/
147 */
148int load_module(char* module)
149{
150int retVal = 1;
151void (*module_start)(void) = NULL;
152char modString[128];
153int fh = -1;
154
155// Check to see if the module has already been loaded
156if(is_module_loaded(module))
157{
158return 1;
159}
160
161sprintf(modString, MODULE_PATH "%s", module);
162fh = open(modString, 0);
163if(fh < 0)
164{
165DBG("WARNING: Unable to locate module %s\n", modString); DBGPAUSE();
166return 0;
167}
168
169unsigned int moduleSize = file_size(fh);
170char* module_base = (char*) malloc(moduleSize);
171if (moduleSize && read(fh, module_base, moduleSize) == moduleSize)
172{
173// Module loaded into memory, parse it
174module_start = parse_mach(module_base, &load_module, &add_symbol, NULL);
175
176if(module_start && module_start != (void*)0xFFFFFFFF)
177{
178// Notify the system that it was laoded
179module_loaded(module, NULL, NULL, 0, 0 /*moduleName, moduleVersion, moduleCompat*/);
180(*module_start)();// Start the module
181DBG("Module %s Loaded.\n", module); DBGPAUSE();
182}
183#if CONFIG_MODULE_DEBUG
184else // The module does not have a valid start function. This may be a library.
185{
186printf("WARNING: Unable to start %s\n", module);
187getchar();
188}
189#else
190else msglog("WARNING: Unable to start %s\n", module);
191#endif
192}
193else
194{
195DBG("Unable to read in module %s\n.", module); DBGPAUSE();
196retVal = 0;
197}
198
199close(fh);
200return retVal;
201}
202
203/*
204 * add_symbol
205 * This function adds a symbol from a module to the list of known symbols
206 * possibly change to a pointer and add this to the Symbol module so that it can
207 * adjust it's internal symbol list (sort) to optimize locating new symbols
208 * NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF
209 */
210long long add_symbol(char* symbol, long long addr, char is64)
211{
212if(is64) return 0xFFFFFFFF; // Fixme
213
214// This only can handle 32bit symbols
215symbolList_t* entry;
216//DBG("Adding symbol %s at 0x%X\n", symbol, addr);
217
218entry = malloc(sizeof(symbolList_t));
219entry->next = moduleSymbols;
220moduleSymbols = entry;
221
222entry->addr = (UInt32)addr;
223entry->symbol = symbol;
224
225if(strcmp(symbol, "start") == 0)
226{
227return addr;
228}
229else
230{
231return 0xFFFFFFFF; // fixme
232}
233}
234
235
236/*
237 * print out the information about the loaded module
238 */
239void module_loaded(const char* name, const char* author, const char* description, UInt32 version, UInt32 compat)
240{
241moduleList_t* new_entry = malloc(sizeof(moduleList_t));
242new_entry->next = loadedModules;
243
244loadedModules = new_entry;
245
246 if(!name) name = "Unknown";
247 if(!author) author = "Unknown";
248 if(!description) description = "";
249
250new_entry->name = name;
251 new_entry->author = author;
252 new_entry->description = description;
253new_entry->version = version;
254 new_entry->compat = compat;
255
256 msglog("Module '%s' by '%s' Loaded.\n", name, author);
257 msglog("\tDescription: %s\n", description);
258 msglog("\tVersion: %d\n", version); // todo: sperate to major.minor.bugfix
259 msglog("\tCompat: %d\n", compat); // todo: ^^^ major.minor.bugfix
260}
261
262int is_module_loaded(const char* name)
263{
264// todo sorted search
265moduleList_t* entry = loadedModules;
266while(entry)
267{
268if(strcmp(entry->name, name) == 0)
269{
270DBG("Located module %s\n", name); DBGPAUSE();
271return 1;
272}
273else
274{
275entry = entry->next;
276}
277
278}
279
280DBG("Module %s not found\n", name); DBGPAUSE();
281return 0;
282}
283
284/*
285 *lookup symbols in all loaded modules. Thins inludes boot syms due to Symbols.dylib construction
286 *
287 */
288unsigned int lookup_all_symbols(const char* name)
289{
290symbolList_t* entry = moduleSymbols;
291while(entry)
292{
293if(strcmp(entry->symbol, name) == 0)
294{
295//DBG("External symbol %s located at 0x%X\n", name, entry->addr);
296return entry->addr;
297}
298else
299{
300entry = entry->next;
301}
302}
303
304#if CONFIG_MODULE_DEBUG
305printf("Unable to locate symbol %s\n", name);
306getchar();
307#endif
308
309if(strcmp(name, VOID_SYMBOL) == 0) return 0xFFFFFFFF;
310// In the event that a symbol does not exist
311// Return a pointer to a void function.
312else return lookup_all_symbols(VOID_SYMBOL);
313}
314
315
316/********************************************************************************/
317/*Module Hook Interface*/
318/********************************************************************************/
319
320
321/*
322 *execute_hook( const char* name )
323 *name - Name of the module hook
324 *If any callbacks have been registered for this hook
325 *they will be executed now in the same order that the
326 *hooks were added.
327*/
328int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)
329{
330DBG("Attempting to execute hook '%s'\n", name); DBGPAUSE();
331moduleHook_t* hook = hook_exists(name);
332
333if(hook)
334{
335// Loop through all callbacks for this module
336callbackList_t* callbacks = hook->callbacks;
337
338while(callbacks)
339{
340// Execute callback
341callbacks->callback(arg1, arg2, arg3, arg4);
342callbacks = callbacks->next;
343}
344DBG("Hook '%s' executed.\n", name); DBGPAUSE();
345return 1;
346}
347else
348{
349// Callback for this hook doesn't exist;
350DBG("No callbacks for '%s' hook.\n", name);
351return 0;
352}
353}
354
355
356
357/*
358 *register_hook_callback( const char* name, void(*callback)())
359 *name - Name of the module hook to attach to.
360 *callbacks - The funciton pointer that will be called when the
361 *hook is executed. When registering a new callback name, the callback is added sorted.
362 *NOTE: the hooks take four void* arguments.
363 */
364void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
365{
366DBG("Adding callback for '%s' hook.\n", name); DBGPAUSE();
367
368moduleHook_t* hook = hook_exists(name);
369
370if(hook)
371{
372// append
373callbackList_t* newCallback = malloc(sizeof(callbackList_t));
374newCallback->next = hook->callbacks;
375hook->callbacks = newCallback;
376newCallback->callback = callback;
377}
378else
379{
380// create new hook
381moduleHook_t* newHook = malloc(sizeof(moduleHook_t));
382newHook->name = name;
383newHook->callbacks = malloc(sizeof(callbackList_t));
384newHook->callbacks->callback = callback;
385newHook->callbacks->next = NULL;
386
387newHook->next = moduleCallbacks;
388moduleCallbacks = newHook;
389
390}
391
392#if CONFIG_MODULE_DEBUG
393//print_hook_list();
394//getchar();
395#endif
396
397}
398
399
400moduleHook_t* hook_exists(const char* name)
401{
402moduleHook_t* hooks = moduleCallbacks;
403
404// look for a hook. If it exists, return the moduleHook_t*,
405// If not, return NULL.
406while(hooks)
407{
408if(strcmp(name, hooks->name) == 0)
409{
410//DBG("Located hook %s\n", name);
411return hooks;
412}
413hooks = hooks->next;
414}
415//DBG("Hook %s does not exist\n", name);
416return NULL;
417
418}
419
420#if CONFIG_MODULE_DEBUG
421void print_hook_list()
422{
423printf("---Hook Table---\n");
424
425moduleHook_t* hooks = moduleCallbacks;
426while(hooks)
427{
428printf("Hook: %s\n", hooks->name);
429hooks = hooks->next;
430}
431}
432
433#endif
434
435/********************************************************************************/
436/*dyld / Linker Interface*/
437/********************************************************************************/
438
439void dyld_stub_binder()
440{
441printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");
442getchar();
443}
444
445#else /* CONFIG_MODULES */
446
447int init_module_system()
448{
449 return 0;
450}
451
452void load_all_modules()
453{
454
455}
456
457int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)
458{
459 return 0;
460}
461#endif

Archive Download this file

Revision: 1247