Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/modules/KextPatcher/kext_patcher.c

Source at commit 598 created 13 years 6 months ago.
By meklort, Kext Patcher initial implimentation, incomplete. Mkexts v2 are partialy handled (need to be recompressed), all others are not handled. Added the zlib library, I may change this into a module in the future.
1/*
2 * Copyright (c) 2010 Evan Lojewski. All rights reserved.
3 *
4 *KextPather
5 *This is an experimental module that I'm looking into implimenting.
6 *The main purpose is to replace the need for programs such as
7 * NetbookInstaller's kext patching routines. THis way, Apple's kexts can be
8 * patched whe loaded instead. (eg: GMA950 kext, Bluetooth + Wifi kexts)
9 */
10
11#include "libsaio.h"
12#include "zlib.h"
13#include "kext_patcher.h"
14#include "pci.h"
15#include "drivers.h"
16#include "mkext.h"
17#include "modules.h"
18
19void patch_kext(TagPtr plist, void* start);
20
21static void * z_alloc(void *, u_int items, u_int size);
22static void z_free(void *, void *ptr);
23
24typedef struct z_mem {
25 uint32_t alloc_size;
26 uint8_t data[0];
27} z_mem;
28
29/*
30 * Space allocation and freeing routines for use by zlib routines.
31 */
32void *
33z_alloc(void * notused __unused, u_int num_items, u_int size)
34{
35 void * result = NULL;
36 z_mem * zmem = NULL;
37 uint32_t total = num_items * size;
38 uint32_t allocSize = total + sizeof(zmem);
39
40 zmem = (z_mem *)malloc(allocSize);
41 if (!zmem) {
42 goto finish;
43 }
44 zmem->alloc_size = allocSize;
45 result = (void *)&(zmem->data);
46finish:
47 return result;
48}
49
50void
51z_free(void * notused __unused, void * ptr)
52{
53 uint32_t * skipper = (uint32_t *)ptr - 1;
54 z_mem * zmem = (z_mem *)skipper;
55 free((void *)zmem);
56 return;
57}
58
59
60unsigned long Mkext_Alder32( unsigned char * buffer, long length );
61
62void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4);
63
64/**
65 ** KextPatcher_start -> module start
66 **Notified the module system that this module will hook into the
67 **LoadMatchedModules and LoadDriverMKext functions
68 **/
69void KextPatcher_start()
70{
71// Hooks into the following:
72//execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL);
73// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
74
75register_hook_callback("PCIDevice", &KextPatcher_hook);
76register_hook_callback("LoadMatchedModules", &kext_loaded);
77register_hook_callback("LoadDriverMKext", &mkext_loaded);
78
79}
80
81/**
82 ** kext_loaded -> Called whenever a kext is in read into memory
83 **This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)
84 **and their plists when they are loaded into memmory
85 **/
86void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3)
87{
88
89//ModulePtr module = moduletmp;
90//long length = *(long*)lengthprt;
91//long length2 = strlen(module->plistAddr);
92// *(long*)lengthprt = length2 + 5 * 1024 * 1024;
93
94//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);
95//getc();
96}
97
98/**
99 ** mkext_loaded -> Called whenever an mkext is in read into memory
100 **This function will be used to patch mkext. Matching kexts will be
101 **Extracted, modified, and then compressed again. Note: I need to determine
102 **what sort of slowdown this will cause and if it's worth implimenting.
103 **/
104
105void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3)
106{
107int version = 0;
108int length = (int) lengthtmp;
109mkext_basic_header* package = packagetmp;
110
111// Verify the MKext.
112 if (( MKEXT_GET_MAGIC(package)!= MKEXT_MAGIC ) ||
113 ( MKEXT_GET_SIGNATURE(package)!= MKEXT_SIGN ) ||
114 ( MKEXT_GET_LENGTH(package)> kLoadSize ) ||
115 ( MKEXT_GET_CHECKSUM(package) !=
116 Mkext_Alder32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )
117 {
118 return;
119// Don't try to patch a b
120 }
121
122
123if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0)
124{
125printf("Invalidating mkext %s\n", filespec);
126// 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it.
127//package->adler32++;
128// NOTE: double check that this is needed
129package->magic = 0x00;
130return;
131}
132
133
134version = MKEXT_GET_VERSION(package);
135
136if(version == 0x01008000) // mkext1
137{
138// mkext1 uses lzss
139mkext1_header* package = packagetmp;
140int i;
141for(i = 0; i < MKEXT_GET_COUNT(package); i++)
142{
143printf("Parsing kext %d\n", i);
144//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);
145// uses decompress_lzss
146// TODO: handle kext
147
148}
149}
150else if((version & 0xFFFF0000) == 0x02000000) // mkext2
151{
152printf("Mkext2 package located at 0x%X\n", package);
153
154// mkext2 uses zlib
155mkext2_header* package = packagetmp;
156z_stream zstream;
157bool zstream_inited = false;
158int zlib_result;
159int plist_offset = MKEXT2_GET_PLIST(package);
160
161char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));
162
163bzero(&zstream, sizeof(zstream));
164zstream.next_in = (UInt8*)((char*)package + plist_offset);
165zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);
166
167zstream.next_out = (UInt8*)plist;
168zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);
169
170zstream.zalloc = z_alloc;
171zstream.zfree = z_free;
172
173zlib_result = inflateInit(&zstream);
174if (Z_OK != zlib_result)
175{
176printf("ZLIB Error: %s\n", zstream.msg);
177getc();
178}
179else
180{
181zstream_inited = true;
182}
183
184
185zlib_result = inflate(&zstream, Z_FINISH);
186printf("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);
187if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)
188{
189//printf("Plist contains %s\n", plist);
190
191config_file_t plistData;
192config_file_t allDicts;
193bzero(&plistData, sizeof(plistData));
194bzero(&allDicts, sizeof(allDicts));
195
196//plist += strlen("<dict><key>_MKEXTInfoDictionaries</key><array>");// Skip kMKEXTInfoDictionariesKey. Causes issues
197// NOTE: there will be an extra </array></dict> at the end
198/*int len =*/ XMLParseFile( plist, &plistData.dictionary );
199
200int count = 0;
201
202count = XMLTagCount(plistData.dictionary);
203if(count != 1)
204{
205error("Mkext has more than one entry, unable to patch.");
206getc();
207return;
208}
209allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey);
210count = XMLTagCount(allDicts.dictionary);
211printf("Element type: %d\n", allDicts.dictionary->type);
212printf("Element tag: %d\n", allDicts.dictionary->tag);
213printf("Element tagNext: %d\n", allDicts.dictionary->tagNext);
214
215printf("Plist contains %d kexts\n", count);
216
217for(; count--; count > 0)
218{
219TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count);
220patch_kext(kextEntry, package);
221}
222
223printf("kexts parsed\n");
224
225
226}
227else
228{
229printf("ZLIB Error: %s\n", zstream.msg);
230getc();
231}
232
233//config_file_t mkextPlist;
234//ParseXMLFile((char*) plist, &mkextPlist.dictionary);
235
236
237
238
239
240/*int i;
241for(i = 0; i < MKEXT_GET_COUNT(package); i++)
242{
243printf("Parsing kext %d\n", i);
244}
245*/
246
247if (zstream_inited) inflateEnd(&zstream);
248
249}
250
251
252printf("Loading %s, length %d, version 0x%x\n", filespec, length, version);
253getc();
254}
255
256// TODO: only handles mkext2 entries
257void patch_kext(TagPtr plist, void* start)
258{
259int exeutable_offset;
260mkext2_file_entry* kext;
261char* bundleID;
262int full_size, compressed_size;
263void* compressed_data;
264z_stream zstream;
265bool zstream_inited = false;
266int zlib_result;
267
268if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return;// Kext is a plist only kext, don't patch
269
270bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));
271exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));
272kext = (void*)((char*)start + exeutable_offset);
273
274full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);
275compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);
276compressed_data = MKEXT2_GET_ENTRY_DATA(kext);
277
278if(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0)
279//if(strcmp(bundleID, "com.apple.driver.AppleACPIBatteryManager") == 0)
280{
281printf("offset is 0x%x\n", exeutable_offset);
282
283char* executable = malloc(full_size);
284
285bzero(&zstream, sizeof(zstream));
286zstream.next_in = (UInt8*)compressed_data;
287zstream.avail_in = compressed_size;
288
289zstream.next_out = (UInt8*)executable;
290zstream.avail_out = full_size;
291
292zstream.zalloc = z_alloc;
293zstream.zfree = z_free;
294
295zlib_result = inflateInit(&zstream);
296if (Z_OK != zlib_result)
297{
298printf("ZLIB Error: %s\n", zstream.msg);
299getc();
300}
301else
302{
303zstream_inited = true;
304}
305
306
307zlib_result = inflate(&zstream, Z_FINISH);
308
309printf("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
310
311if (zstream_inited) inflateEnd(&zstream);
312
313free(executable);
314
315printf("\n");
316
317getc();
318}
319}
320
321
322void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4)
323{
324//pci_dt_t* current = arg1;
325}

Archive Download this file

Revision: 598