Root/
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 | ␊ |
14 | extern 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␊ |
25 | UInt64 textAddress = 0;␊ |
26 | UInt64 textSection = 0;␊ |
27 | ␊ |
28 | void* symbols_module_start = (void*)0xFFFFFFFF;␉// Global, value is populated by the makefile with actual address␊ |
29 | ␊ |
30 | /** Internal symbols, however there are accessor methods **/␊ |
31 | moduleHook_t* moduleCallbacks = NULL;␊ |
32 | moduleList_t* loadedModules = NULL;␊ |
33 | symbolList_t* moduleSymbols = NULL;␊ |
34 | unsigned 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 | */␊ |
42 | int init_module_system()␊ |
43 | {␊ |
44 | // Start any modules that were compiled in first.␊ |
45 | start_built_in_modules();␊ |
46 | ␊ |
47 | ␊ |
48 | ␉int retVal = 0;␊ |
49 | ␉void (*module_start)(void) = NULL;␊ |
50 | ␉char* module_data = symbols_module_start + BOOT2_ADDR;␊ |
51 | ␊ |
52 | ␉// Intialize module system␊ |
53 | ␉if(symbols_module_start != (void*)0xFFFFFFFF)␊ |
54 | ␉{␊ |
55 | ␉␉// Module system was compiled in (Symbols.dylib addr known)␊ |
56 | ␉␉module_start = parse_mach(module_data, &load_module, &add_symbol, NULL);␊ |
57 | ␉␉␊ |
58 | ␉␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
59 | ␉␉{␊ |
60 | ␉␉␉// Notify the system that it was laoded␊ |
61 | ␉␉␉module_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.␊ |
64 | ␉␉␉execute_hook("ModulesLoaded", NULL, NULL, NULL, NULL);␊ |
65 | ␉␉␉DBG("Module %s Loaded.\n", SYMBOLS_MODULE);␊ |
66 | ␉␉␉retVal = 1;␊ |
67 | ␊ |
68 | ␉␉}␊ |
69 | ␉␉else␊ |
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 | ␉}␊ |
92 | ␉return retVal;␊ |
93 | }␊ |
94 | ␊ |
95 | void 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 | */␊ |
117 | void load_all_modules()␊ |
118 | {␊ |
119 | ␉char* name;␊ |
120 | ␉long flags;␊ |
121 | ␉long time;␊ |
122 | ␉struct dirstuff* moduleDir = opendir("/Extra/modules/");␊ |
123 | ␉while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)␊ |
124 | ␉{␊ |
125 | ␉␉if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)␊ |
126 | ␉␉{␊ |
127 | ␉␉␉char* tmp = malloc(strlen(name) + 1);␊ |
128 | ␉␉␉strcpy(tmp, name);␊ |
129 | ␉␉␉␊ |
130 | ␉␉␉if(!load_module(tmp))␊ |
131 | ␉␉␉{␊ |
132 | ␉␉␉␉// failed to load␊ |
133 | ␉␉␉␉// free(tmp);␊ |
134 | ␉␉␉}␊ |
135 | ␉␉}␊ |
136 | ␉␉else ␊ |
137 | ␉␉{␊ |
138 | ␉␉␉DBG("Ignoring %s\n", name);␊ |
139 | ␉␉}␊ |
140 | ␊ |
141 | ␉}␊ |
142 | }␊ |
143 | ␊ |
144 | ␊ |
145 | /*␊ |
146 | * Load a module file in /Extra/modules/␊ |
147 | */␊ |
148 | int load_module(char* module)␊ |
149 | {␊ |
150 | ␉int retVal = 1;␊ |
151 | ␉void (*module_start)(void) = NULL;␊ |
152 | ␉char modString[128];␊ |
153 | ␉int fh = -1;␊ |
154 | ␊ |
155 | ␉// Check to see if the module has already been loaded␊ |
156 | ␉if(is_module_loaded(module))␊ |
157 | ␉{␊ |
158 | ␉␉return 1;␊ |
159 | ␉}␊ |
160 | ␉␊ |
161 | ␉sprintf(modString, MODULE_PATH "%s", module);␊ |
162 | ␉fh = open(modString, 0);␊ |
163 | ␉if(fh < 0)␊ |
164 | ␉{␊ |
165 | ␉␉DBG("WARNING: Unable to locate module %s\n", modString); DBGPAUSE();␊ |
166 | ␉␉return 0;␊ |
167 | ␉}␊ |
168 | ␉␊ |
169 | ␉unsigned int moduleSize = file_size(fh);␊ |
170 | ␉char* module_base = (char*) malloc(moduleSize);␊ |
171 | ␉if (moduleSize && read(fh, module_base, moduleSize) == moduleSize)␊ |
172 | ␉{␊ |
173 | ␉␉// Module loaded into memory, parse it␊ |
174 | ␉␉module_start = parse_mach(module_base, &load_module, &add_symbol, NULL);␊ |
175 | ␊ |
176 | ␉␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
177 | ␉␉{␊ |
178 | ␉␉␉// Notify the system that it was laoded␊ |
179 | ␉␉␉module_loaded(module, NULL, NULL, 0, 0 /*moduleName, moduleVersion, moduleCompat*/);␊ |
180 | ␉␉␉(*module_start)();␉// Start the module␊ |
181 | ␉␉␉DBG("Module %s Loaded.\n", module); DBGPAUSE();␊ |
182 | ␉␉}␊ |
183 | #if CONFIG_MODULE_DEBUG␊ |
184 | ␉␉else // The module does not have a valid start function. This may be a library.␊ |
185 | ␉␉{␊ |
186 | ␉␉␉printf("WARNING: Unable to start %s\n", module);␊ |
187 | ␉␉␉getchar();␊ |
188 | ␉␉}␊ |
189 | #else␊ |
190 | ␉␉else msglog("WARNING: Unable to start %s\n", module);␊ |
191 | #endif␊ |
192 | ␉}␊ |
193 | ␉else␊ |
194 | ␉{␊ |
195 | ␉␉DBG("Unable to read in module %s\n.", module); DBGPAUSE();␊ |
196 | ␉␉retVal = 0;␊ |
197 | ␉}␊ |
198 | ␊ |
199 | ␉close(fh);␊ |
200 | ␉return 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 | */␊ |
210 | long long add_symbol(char* symbol, long long addr, char is64)␊ |
211 | {␊ |
212 | ␉if(is64) return 0xFFFFFFFF; // Fixme␊ |
213 | ␊ |
214 | ␉// This only can handle 32bit symbols ␊ |
215 | ␉symbolList_t* entry;␊ |
216 | ␉//DBG("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
217 | ␉␊ |
218 | ␉entry = malloc(sizeof(symbolList_t));␊ |
219 | ␉entry->next = moduleSymbols;␊ |
220 | ␉moduleSymbols = entry;␊ |
221 | ␉␊ |
222 | ␉entry->addr = (UInt32)addr;␊ |
223 | ␉entry->symbol = symbol;␊ |
224 | ␉␊ |
225 | ␉if(strcmp(symbol, "start") == 0)␊ |
226 | ␉{␊ |
227 | ␉␉return addr;␊ |
228 | ␉}␊ |
229 | ␉else␊ |
230 | ␉{␊ |
231 | ␉␉return 0xFFFFFFFF; // fixme␊ |
232 | ␉}␊ |
233 | }␊ |
234 | ␊ |
235 | ␊ |
236 | /*␊ |
237 | * print out the information about the loaded module␊ |
238 | */␊ |
239 | void module_loaded(const char* name, const char* author, const char* description, UInt32 version, UInt32 compat)␊ |
240 | {␊ |
241 | ␉moduleList_t* new_entry = malloc(sizeof(moduleList_t));␊ |
242 | ␉new_entry->next = loadedModules;␊ |
243 | ␊ |
244 | ␉loadedModules = new_entry;␊ |
245 | ␉␊ |
246 | if(!name) name = "Unknown";␊ |
247 | if(!author) author = "Unknown";␊ |
248 | if(!description) description = "";␊ |
249 | ␊ |
250 | ␉new_entry->name = name;␊ |
251 | new_entry->author = author;␊ |
252 | new_entry->description = description;␊ |
253 | ␉new_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 | ␊ |
262 | int is_module_loaded(const char* name)␊ |
263 | {␊ |
264 | ␉// todo sorted search␊ |
265 | ␉moduleList_t* entry = loadedModules;␊ |
266 | ␉while(entry)␊ |
267 | ␉{␊ |
268 | ␉␉if(strcmp(entry->name, name) == 0)␊ |
269 | ␉␉{␊ |
270 | ␉␉␉DBG("Located module %s\n", name); DBGPAUSE();␊ |
271 | ␉␉␉return 1;␊ |
272 | ␉␉}␊ |
273 | ␉␉else␊ |
274 | ␉␉{␊ |
275 | ␉␉␉entry = entry->next;␊ |
276 | ␉␉}␊ |
277 | ␊ |
278 | ␉}␊ |
279 | ␉␊ |
280 | ␉DBG("Module %s not found\n", name); DBGPAUSE();␊ |
281 | ␉return 0;␊ |
282 | }␊ |
283 | ␊ |
284 | /*␊ |
285 | *␉lookup symbols in all loaded modules. Thins inludes boot syms due to Symbols.dylib construction␊ |
286 | *␊ |
287 | */␊ |
288 | unsigned int lookup_all_symbols(const char* name)␊ |
289 | {␊ |
290 | ␉symbolList_t* entry = moduleSymbols;␊ |
291 | ␉while(entry)␊ |
292 | ␉{␊ |
293 | ␉␉if(strcmp(entry->symbol, name) == 0)␊ |
294 | ␉␉{␊ |
295 | ␉␉␉//DBG("External symbol %s located at 0x%X\n", name, entry->addr);␊ |
296 | ␉␉␉return entry->addr;␊ |
297 | ␉␉}␊ |
298 | ␉␉else␊ |
299 | ␉␉{␊ |
300 | ␉␉␉entry = entry->next;␊ |
301 | ␉␉}␊ |
302 | ␉}␊ |
303 | ␉␊ |
304 | #if CONFIG_MODULE_DEBUG␊ |
305 | ␉printf("Unable to locate symbol %s\n", name);␊ |
306 | ␉getchar();␊ |
307 | #endif␊ |
308 | ␉␊ |
309 | ␉if(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.␊ |
312 | ␉else 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 | */␊ |
328 | int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)␊ |
329 | {␊ |
330 | ␉DBG("Attempting to execute hook '%s'\n", name); DBGPAUSE();␊ |
331 | ␉moduleHook_t* hook = hook_exists(name);␊ |
332 | ␉␊ |
333 | ␉if(hook)␊ |
334 | ␉{␊ |
335 | ␉␉// Loop through all callbacks for this module␊ |
336 | ␉␉callbackList_t* callbacks = hook->callbacks;␊ |
337 | ␊ |
338 | ␉␉while(callbacks)␊ |
339 | ␉␉{␊ |
340 | ␉␉␉// Execute callback␊ |
341 | ␉␉␉callbacks->callback(arg1, arg2, arg3, arg4);␊ |
342 | ␉␉␉callbacks = callbacks->next;␊ |
343 | ␉␉}␊ |
344 | ␉␉DBG("Hook '%s' executed.\n", name); DBGPAUSE();␊ |
345 | ␉␉return 1;␊ |
346 | ␉}␊ |
347 | ␉else␊ |
348 | ␉{␊ |
349 | ␉␉// Callback for this hook doesn't exist;␊ |
350 | ␉␉DBG("No callbacks for '%s' hook.\n", name);␊ |
351 | ␉␉return 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 | */␊ |
364 | void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))␊ |
365 | {␉␊ |
366 | ␉DBG("Adding callback for '%s' hook.\n", name); DBGPAUSE();␊ |
367 | ␉␊ |
368 | ␉moduleHook_t* hook = hook_exists(name);␊ |
369 | ␉␊ |
370 | ␉if(hook)␊ |
371 | ␉{␊ |
372 | ␉␉// append␊ |
373 | ␉␉callbackList_t* newCallback = malloc(sizeof(callbackList_t));␊ |
374 | ␉␉newCallback->next = hook->callbacks;␊ |
375 | ␉␉hook->callbacks = newCallback;␊ |
376 | ␉␉newCallback->callback = callback;␊ |
377 | ␉}␊ |
378 | ␉else␊ |
379 | ␉{␊ |
380 | ␉␉// create new hook␊ |
381 | ␉␉moduleHook_t* newHook = malloc(sizeof(moduleHook_t));␉␉␊ |
382 | ␉␉newHook->name = name;␊ |
383 | ␉␉newHook->callbacks = malloc(sizeof(callbackList_t));␊ |
384 | ␉␉newHook->callbacks->callback = callback;␊ |
385 | ␉␉newHook->callbacks->next = NULL;␊ |
386 | ␉␉␊ |
387 | ␉␉newHook->next = moduleCallbacks;␊ |
388 | ␉␉moduleCallbacks = newHook;␊ |
389 | ␉␉␊ |
390 | ␉}␊ |
391 | ␉␊ |
392 | #if CONFIG_MODULE_DEBUG␊ |
393 | ␉//print_hook_list();␊ |
394 | ␉//getchar();␊ |
395 | #endif␊ |
396 | ␉␊ |
397 | }␊ |
398 | ␊ |
399 | ␊ |
400 | moduleHook_t* hook_exists(const char* name)␊ |
401 | {␊ |
402 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
403 | ␉␊ |
404 | ␉// look for a hook. If it exists, return the moduleHook_t*,␊ |
405 | ␉// If not, return NULL.␊ |
406 | ␉while(hooks)␊ |
407 | ␉{␊ |
408 | ␉␉if(strcmp(name, hooks->name) == 0)␊ |
409 | ␉␉{␊ |
410 | ␉␉␉//DBG("Located hook %s\n", name);␊ |
411 | ␉␉␉return hooks;␊ |
412 | ␉␉}␊ |
413 | ␉␉hooks = hooks->next;␊ |
414 | ␉}␊ |
415 | ␉//DBG("Hook %s does not exist\n", name);␊ |
416 | ␉return NULL;␊ |
417 | ␉␊ |
418 | }␊ |
419 | ␊ |
420 | #if CONFIG_MODULE_DEBUG␊ |
421 | void print_hook_list()␊ |
422 | {␊ |
423 | ␉printf("---Hook Table---\n");␊ |
424 | ␉␊ |
425 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
426 | ␉while(hooks)␊ |
427 | ␉{␊ |
428 | ␉␉printf("Hook: %s\n", hooks->name);␊ |
429 | ␉␉hooks = hooks->next;␊ |
430 | ␉}␊ |
431 | }␊ |
432 | ␊ |
433 | #endif␊ |
434 | ␊ |
435 | /********************************************************************************/␊ |
436 | /*␉dyld / Linker Interface␉␉␉␉␉␉␉␉␉␉␉␉␉␉*/␊ |
437 | /********************************************************************************/␊ |
438 | ␊ |
439 | void dyld_stub_binder()␊ |
440 | {␊ |
441 | ␉printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");␊ |
442 | ␉getchar();␊ |
443 | }␊ |
444 | ␊ |
445 | #else /* CONFIG_MODULES */␊ |
446 | ␊ |
447 | int init_module_system()␊ |
448 | {␊ |
449 | return 0;␊ |
450 | }␊ |
451 | ␊ |
452 | void load_all_modules()␊ |
453 | {␊ |
454 | ␊ |
455 | }␊ |
456 | ␊ |
457 | int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)␊ |
458 | {␊ |
459 | return 0;␊ |
460 | }␊ |
461 | #endif |