Chameleon

Chameleon Svn Source Tree

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

Source at commit 1406 created 12 years 10 months ago.
By meklort, Revert drivers.c so that kexts are only loaded when OSBundleRequired is set and that value is not safe mode. Added some comments about it too.
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: 1406