Root/
Source at commit 607 created 13 years 5 months ago. By meklort, Kext patcher can now add BCM43xx devices to the wifi kext. Only patches the kexts if associated devices exist, otherwise doesn't touch the mkext. | |
---|---|
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 | #include "hex_editor.h"␊ |
19 | ␊ |
20 | ␊ |
21 | #ifndef DEBUG_KEXT_PATCHER␊ |
22 | #define DEBUG_KEXT_PATCHER 0␊ |
23 | #endif␊ |
24 | ␊ |
25 | #if DEBUG_KEXT_PATCHER␊ |
26 | #define DBG(x...)␉printf(x)␊ |
27 | #else␊ |
28 | #define DBG(x...)␊ |
29 | #endif␊ |
30 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
31 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start);␊ |
32 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
33 | ␊ |
34 | static void * z_alloc(void *, u_int items, u_int size);␊ |
35 | static void z_free(void *, void *ptr);␊ |
36 | ␊ |
37 | uint16_t patch_gma_deviceid = 0;␊ |
38 | uint16_t patch_bcm_deviceid = 0;␊ |
39 | ␊ |
40 | #define NEEDS_PATCHING␉␉(patch_bcm_deviceid || patch_gma_deviceid)␊ |
41 | ␊ |
42 | typedef struct z_mem {␊ |
43 | uint32_t alloc_size;␊ |
44 | uint8_t data[0];␊ |
45 | } z_mem;␊ |
46 | ␊ |
47 | /*␊ |
48 | * Space allocation and freeing routines for use by zlib routines.␊ |
49 | */␊ |
50 | void *␊ |
51 | z_alloc(void * notused __unused, u_int num_items, u_int size)␊ |
52 | {␊ |
53 | void * result = NULL;␊ |
54 | z_mem * zmem = NULL;␊ |
55 | uint32_t total = num_items * size;␊ |
56 | uint32_t allocSize = total + sizeof(zmem);␊ |
57 | ␊ |
58 | zmem = (z_mem *)malloc(allocSize);␊ |
59 | if (!zmem) {␊ |
60 | goto finish;␊ |
61 | }␊ |
62 | zmem->alloc_size = allocSize;␊ |
63 | result = (void *)&(zmem->data);␊ |
64 | finish:␊ |
65 | return result;␊ |
66 | }␊ |
67 | ␊ |
68 | void␊ |
69 | z_free(void * notused __unused, void * ptr)␊ |
70 | {␊ |
71 | uint32_t * skipper = (uint32_t *)ptr - 1;␊ |
72 | z_mem * zmem = (z_mem *)skipper;␊ |
73 | free((void *)zmem);␊ |
74 | return;␊ |
75 | }␊ |
76 | ␊ |
77 | ␊ |
78 | unsigned long Mkext_Alder32( unsigned char * buffer, long length );␊ |
79 | ␊ |
80 | void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4);␊ |
81 | ␊ |
82 | /**␊ |
83 | ** KextPatcher_start -> module start␊ |
84 | **␉␉Notified the module system that this module will hook into the ␊ |
85 | **␉␉LoadMatchedModules and LoadDriverMKext functions␊ |
86 | **/␊ |
87 | void KextPatcher_start()␊ |
88 | {␉␉␊ |
89 | ␉// Hooks into the following:␊ |
90 | ␉//␉execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL);␊ |
91 | ␉// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);␊ |
92 | ␊ |
93 | ␉register_hook_callback("PCIDevice", &KextPatcher_hook);␊ |
94 | ␉//register_hook_callback("LoadMatchedModules", &kext_loaded); ␊ |
95 | ␉register_hook_callback("LoadDriverMKext", &mkext_loaded); ␊ |
96 | ␊ |
97 | }␊ |
98 | ␊ |
99 | /**␊ |
100 | ** kext_loaded -> Called whenever a kext is in read into memory␊ |
101 | **␉␉This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)␊ |
102 | **␉␉and their plists when they are loaded into memmory␊ |
103 | **/␊ |
104 | void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3)␊ |
105 | {␊ |
106 | ␉␊ |
107 | ␉//ModulePtr module = moduletmp;␊ |
108 | ␉//long length = *(long*)lengthprt;␊ |
109 | ␉//long length2 = strlen(module->plistAddr);␊ |
110 | ␉// *(long*)lengthprt = length2 + 5 * 1024 * 1024;␊ |
111 | ␊ |
112 | ␉//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);␊ |
113 | ␉//getc();␊ |
114 | }␊ |
115 | ␊ |
116 | /**␊ |
117 | ** mkext_loaded -> Called whenever an mkext is in read into memory␊ |
118 | **␉␉This function will be used to patch mkext. Matching kexts will be␊ |
119 | **␉␉Extracted, modified, and then compressed again. Note: I need to determine␊ |
120 | **␉␉what sort of slowdown this will cause and if it's worth implimenting.␊ |
121 | **/␊ |
122 | ␊ |
123 | void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3)␊ |
124 | {␊ |
125 | ␉if(!NEEDS_PATCHING) return;␉// No need to apply a patch, hardware doesn't need it␊ |
126 | ␉␊ |
127 | ␉int version = 0;␊ |
128 | ␉//int length = *((int*)lengthtmp);␊ |
129 | ␉mkext_basic_header* package = packagetmp;␊ |
130 | ␊ |
131 | ␉// Verify the MKext.␊ |
132 | if (( MKEXT_GET_MAGIC(package)␉␉!= MKEXT_MAGIC ) ||␊ |
133 | ( MKEXT_GET_SIGNATURE(package)␉!= MKEXT_SIGN ) ||␊ |
134 | ( MKEXT_GET_LENGTH(package)␉␉> kLoadSize )␉ ||␊ |
135 | ( MKEXT_GET_CHECKSUM(package) !=␊ |
136 | ␉␉ Mkext_Alder32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )␊ |
137 | {␊ |
138 | return;␊ |
139 | ␉␉// Don't try to patch a b␊ |
140 | }␉␊ |
141 | ␉␊ |
142 | ␉/*␊ |
143 | ␉if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0)␊ |
144 | ␉{␊ |
145 | ␉␉printf("Invalidating mkext %s\n", filespec);␊ |
146 | ␉␉// 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it.␊ |
147 | ␉␉//package->adler32++;␊ |
148 | ␉␉// NOTE: double check that this is needed␊ |
149 | ␉␉package->magic = 0x00;␊ |
150 | ␉␉return;␊ |
151 | ␉}*/␊ |
152 | ␉␊ |
153 | ␉␊ |
154 | ␉version = MKEXT_GET_VERSION(package);␊ |
155 | ␉␊ |
156 | ␉if(version == 0x01008000) // mkext1␊ |
157 | ␉{␊ |
158 | ␉␉// mkext1 uses lzss␊ |
159 | ␉␉mkext1_header* package = packagetmp;␊ |
160 | ␉␉int i;␊ |
161 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
162 | ␉␉{␊ |
163 | ␉␉␉DBG("Parsing kext %d\n", i);␊ |
164 | ␉␉␉//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);␊ |
165 | ␉␉␉// uses decompress_lzss␊ |
166 | ␉␉␉// TODO: handle kext␊ |
167 | ␊ |
168 | ␉␉}␊ |
169 | ␉}␊ |
170 | ␉else if((version & 0xFFFF0000) == 0x02000000) // mkext2␊ |
171 | ␉{␊ |
172 | ␉␉DBG("Mkext2 package located at 0x%X\n", package);␊ |
173 | ␊ |
174 | ␉␉// mkext2 uses zlib␉␉␊ |
175 | ␉␉mkext2_header* package = packagetmp;␊ |
176 | ␉␉z_stream zstream;␊ |
177 | ␉␉bool zstream_inited = false;␊ |
178 | ␉␉int zlib_result;␊ |
179 | ␉␉int plist_offset = MKEXT2_GET_PLIST(package);␊ |
180 | ␉␉␊ |
181 | ␉␉char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
182 | ␉␉␊ |
183 | ␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
184 | ␉␉zstream.next_in = (UInt8*)((char*)package + plist_offset);␊ |
185 | ␉␉zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
186 | ␉␉␊ |
187 | ␉␉zstream.next_out = (UInt8*)plist;␊ |
188 | ␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
189 | ␉␉␊ |
190 | ␉␉zstream.zalloc = z_alloc;␊ |
191 | ␉␉zstream.zfree = z_free;␊ |
192 | ␉␉␉␉␊ |
193 | ␉␉zlib_result = inflateInit(&zstream);␊ |
194 | ␉␉if (Z_OK != zlib_result)␊ |
195 | ␉␉{␊ |
196 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
197 | ␉␉␉getc();␊ |
198 | ␉␉}␊ |
199 | ␉␉else ␊ |
200 | ␉␉{␊ |
201 | ␉␉␉zstream_inited = true;␊ |
202 | ␉␉}␊ |
203 | ␊ |
204 | ␉␉␊ |
205 | ␉␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
206 | ␉␉if (zstream_inited) inflateEnd(&zstream);␊ |
207 | ␊ |
208 | ␉␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);␊ |
209 | ␉␉if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)␊ |
210 | ␉␉{␉␉␉␊ |
211 | ␉␉␉config_file_t plistData;␊ |
212 | ␉␉␉config_file_t allDicts;␊ |
213 | ␉␉␉bzero(&plistData, sizeof(plistData));␊ |
214 | ␉␉␉bzero(&allDicts, sizeof(allDicts));␊ |
215 | ␉␉␉␊ |
216 | ␉␉␉XMLParseFile( plist, &plistData.dictionary );␊ |
217 | ␊ |
218 | ␉␉␉int count = 0;␊ |
219 | ␊ |
220 | ␉␉␉allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey);␊ |
221 | ␉␉␉count = XMLTagCount(allDicts.dictionary);␊ |
222 | ␊ |
223 | ␉␉␉DBG("Plist contains %d kexts\n", count);␊ |
224 | ␉␉␉␊ |
225 | ␉␉␉␊ |
226 | ␉␉␉bool patched = false;␊ |
227 | ␉␉␉for(; count--; count > 0)␊ |
228 | ␉␉␉{␊ |
229 | ␉␉␉␉TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count);␊ |
230 | ␉␉␉␉patched |= patch_kext(kextEntry, plist, package);␊ |
231 | ␉␉␉}␊ |
232 | ␉␉␉␊ |
233 | ␊ |
234 | ␉␉␉if(patched)␊ |
235 | ␉␉␉{␊ |
236 | ␉␉␉␉zstream_inited = false;␊ |
237 | ␉␉␉␉// Recompress the plist␊ |
238 | ␉␉␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
239 | ␉␉␉␉zstream.next_in = (UInt8*)plist;␊ |
240 | ␉␉␉␉zstream.next_out = (UInt8*)package + plist_offset;␊ |
241 | ␉␉␉␉zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
242 | ␉␉␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2;␉// Give us some extra free space, just in case␊ |
243 | ␉␉␉␉zstream.zalloc = Z_NULL;␊ |
244 | ␉␉␉␉zstream.zfree = Z_NULL;␊ |
245 | ␉␉␉␉zstream.opaque = Z_NULL;␊ |
246 | ␉␉␉␉␊ |
247 | ␉␉␉␉␊ |
248 | ␉␉␉␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
249 | ␉␉␉␉if (Z_OK != zlib_result) {␊ |
250 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
251 | ␉␉␉␉␉getc();␊ |
252 | ␉␉␉␉}␊ |
253 | ␉␉␉␉else ␊ |
254 | ␉␉␉␉{␊ |
255 | ␉␉␉␉␉zstream_inited = true;␊ |
256 | ␉␉␉␉}␊ |
257 | ␉␉␉␉␊ |
258 | ␉␉␉␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
259 | ␉␉␉␉␊ |
260 | ␉␉␉␉if (zlib_result == Z_STREAM_END)␊ |
261 | ␉␉␉␉{␊ |
262 | ␉␉␉␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
263 | ␉␉␉␉} ␊ |
264 | ␉␉␉␉else if (zlib_result == Z_OK)␊ |
265 | ␉␉␉␉{␊ |
266 | ␉␉␉␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
267 | ␉␉␉␉␉ */␊ |
268 | ␉␉␉␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
269 | ␉␉␉␉␉␊ |
270 | ␉␉␉␉} ␊ |
271 | ␉␉␉␉else if (zlib_result != Z_STREAM_ERROR)␊ |
272 | ␉␉␉␉{␊ |
273 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
274 | ␉␉␉␉␉getc();␊ |
275 | ␉␉␉␉}␊ |
276 | ␉␉␉␉␊ |
277 | ␉␉␉␉if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package))␊ |
278 | ␉␉␉␉{␊ |
279 | ␉␉␉␉␉// Update the mkext length␊ |
280 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out);␊ |
281 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
282 | ␉␉␉␉␉*((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
283 | ␉␉␉␉␉*((int*)lengthtmp) += zstream.total_out;␊ |
284 | ␉␉␉␉}␊ |
285 | ␉␉␉␉␉␉␉␉␊ |
286 | ␉␉␉␉if (zstream_inited) deflateEnd(&zstream);␊ |
287 | ␉␉␉␉␊ |
288 | ␉␉␉␉␊ |
289 | ␉␉␉␉␊ |
290 | ␉␉␉␉// re alder32 the new mkext2 package␊ |
291 | ␉␉␉␉MKEXT_HDR_CAST(package)->adler32 = ␊ |
292 | ␉␉␉␉␉MKEXT_SWAP(Mkext_Alder32((unsigned char *)&package->version,␊ |
293 | ␉␉␉␉␉␉␉␉␉␉␉ MKEXT_GET_LENGTH(package) - 0x10));␊ |
294 | ␉␉␉}␊ |
295 | ␉␉}␊ |
296 | ␉␉else␊ |
297 | ␉␉{␊ |
298 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
299 | ␉␉␉getc();␊ |
300 | ␉␉}␊ |
301 | ␊ |
302 | ␉␉//config_file_t mkextPlist;␊ |
303 | ␉␉//ParseXMLFile((char*) plist, &mkextPlist.dictionary);␊ |
304 | ␉␉␊ |
305 | ␉␉␊ |
306 | ␉␉␊ |
307 | ␉␉␊ |
308 | ␉␉␊ |
309 | ␉␉/*␉␉int i;␊ |
310 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
311 | ␉␉{␊ |
312 | ␉␉␉printf("Parsing kext %d\n", i);␊ |
313 | ␉␉}␊ |
314 | ␉␉*/␊ |
315 | ␉␉␊ |
316 | ␊ |
317 | ␉}␊ |
318 | ␊ |
319 | ␉␊ |
320 | ␉DBG("Loading %s, length %d, version 0x%x\n", filespec, length, version);␊ |
321 | ␉//getc();␊ |
322 | }␊ |
323 | ␊ |
324 | // FIXME: only handles mkext2 entries␊ |
325 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
326 | {␊ |
327 | ␉char* bundleID;␊ |
328 | ␉␊ |
329 | ␉if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return false;␉// Kext is a plist only kext, don't patch␊ |
330 | ␉␊ |
331 | ␉bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));␊ |
332 | ␉␊ |
333 | ␉␊ |
334 | ␉if(patch_gma_deviceid &&␊ |
335 | ␉ (␊ |
336 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||␊ |
337 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)␊ |
338 | ␉␉ )␊ |
339 | ␉ )␊ |
340 | ␉{␊ |
341 | ␉␉return patch_gma_kexts(plist, plistbuffer, start);␊ |
342 | ␉}␊ |
343 | ␉else if(patch_bcm_deviceid && (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0))␊ |
344 | ␉{␊ |
345 | ␉␉return patch_bcm_kext(plist, plistbuffer, start);␊ |
346 | ␊ |
347 | ␉}␊ |
348 | ␉return false;␊ |
349 | }␊ |
350 | ␊ |
351 | void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
352 | {␊ |
353 | ␉pci_dt_t* current = arg1;␊ |
354 | ␉if(current)␊ |
355 | ␉{␊ |
356 | ␉␉if(current->class_id == PCI_CLASS_DISPLAY_VGA)␊ |
357 | ␉␉{␊ |
358 | ␉␉␉if(current->vendor_id == 0x8086 && current->device_id == 0x27AE)␊ |
359 | ␉␉␉{␊ |
360 | ␉␉␉␉// TODO: patche based on dev id.␊ |
361 | ␉␉␉␉patch_gma_deviceid = current->device_id;␊ |
362 | ␉␉␉}␊ |
363 | ␉␉}␊ |
364 | ␉␉else if(current->class_id == PCI_CLASS_NETWORK_OTHER) ␊ |
365 | ␉␉{␊ |
366 | ␉␉␉// Patch BCM43xx␊ |
367 | ␉␉␉if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300))␊ |
368 | ␉␉␉{␊ |
369 | ␉␉␉␉patch_bcm_deviceid = current->device_id;␊ |
370 | ␉␉␉}␊ |
371 | ␉␉}␊ |
372 | ␉}␊ |
373 | }␊ |
374 | ␊ |
375 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
376 | {␊ |
377 | ␉TagPtr personality;␊ |
378 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
379 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"Broadcom 802.11 PCI");␉␊ |
380 | ␉TagPtr match_names =XMLCastArray(XMLGetProperty(personality, (const char*)"IONameMatch"));␊ |
381 | ␊ |
382 | ␉␊ |
383 | ␉char* new_str = malloc(strlen("pci14e4,xxxx")+1);␊ |
384 | ␉sprintf(new_str, "pci14e4,%02x", patch_bcm_deviceid);␊ |
385 | ␊ |
386 | ␉// Check to see if we *really* need to modify the plist, if not, return false␊ |
387 | ␉// so that *if* this were going ot be the only modified kext, the repacking code␊ |
388 | ␉// won't need to be executed.␊ |
389 | ␉int count = XMLTagCount(match_names);␊ |
390 | ␉while(count)␊ |
391 | ␉{␊ |
392 | ␉␉count--;␊ |
393 | ␉␉TagPtr replace =␉XMLGetElement(match_names, count);␉// Modify the second entry␊ |
394 | ␉␉char* orig_string = XMLCastString(replace);␊ |
395 | ␉␉if(strcmp(orig_string, new_str) == 0) return false;␊ |
396 | ␉}␊ |
397 | ␊ |
398 | ␉␊ |
399 | ␉TagPtr replace =␉XMLGetElement(match_names, 1);␉// Modify the second entry␊ |
400 | ␉char* orig_string = XMLCastString(replace);␊ |
401 | ␉␊ |
402 | ␉DBG("Attemting to replace '%s' with '%s'\n", orig_string, new_str);␊ |
403 | ␊ |
404 | ␉// TODO: verify string doesn't exist first.␊ |
405 | ␉␊ |
406 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(replace));␊ |
407 | ␉␊ |
408 | ␉return true;␊ |
409 | }␊ |
410 | ␊ |
411 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start)␊ |
412 | {␊ |
413 | ␉int exeutable_offset, full_size, compressed_size;␊ |
414 | ␉TagPtr personality;␊ |
415 | ␉long offset;␊ |
416 | ␉int zlib_result;␊ |
417 | ␉z_stream zstream;␊ |
418 | ␉bool zstream_inited = false;␊ |
419 | ␉mkext2_file_entry* kext;␊ |
420 | ␉void* compressed_data;␊ |
421 | ␊ |
422 | ␉exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
423 | ␉kext = (void*)((char*)start + exeutable_offset);␊ |
424 | ␊ |
425 | ␉full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
426 | ␉compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
427 | ␉compressed_data = MKEXT2_GET_ENTRY_DATA(kext);␊ |
428 | ␉␊ |
429 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
430 | ␉if(XMLGetProperty(personality, (const char*)"Intel915"))␊ |
431 | ␉{␊ |
432 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"Intel915");␊ |
433 | ␉}␊ |
434 | ␉else␊ |
435 | ␉{␊ |
436 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer");␉␊ |
437 | ␉}␊ |
438 | #if DEBUG_KEXT_PATCHER␊ |
439 | ␉char* pcimatch =␉XMLCastString(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
440 | #endif␊ |
441 | ␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
442 | ␉␊ |
443 | ␉replace_string("0x27A28086", "0x27AE8086", plistbuffer + offset);␊ |
444 | ␉␊ |
445 | ␉DBG("Located kext %s\n", bundleID);␊ |
446 | ␉DBG("PCI Match offset = %d, string = %s\n", offset, pcimatch);␊ |
447 | ␉char* executable = malloc(full_size);␊ |
448 | ␉␊ |
449 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
450 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
451 | ␉zstream.avail_in = compressed_size;␊ |
452 | ␉␊ |
453 | ␉zstream.next_out = (UInt8*)executable;␊ |
454 | ␉zstream.avail_out = full_size;␊ |
455 | ␉␊ |
456 | ␉zstream.zalloc = z_alloc;␊ |
457 | ␉zstream.zfree = z_free;␊ |
458 | ␉␊ |
459 | ␉zlib_result = inflateInit(&zstream);␊ |
460 | ␉if (Z_OK != zlib_result)␊ |
461 | ␉{␊ |
462 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
463 | ␉␉getc();␊ |
464 | ␉}␊ |
465 | ␉else ␊ |
466 | ␉{␊ |
467 | ␉␉zstream_inited = true;␊ |
468 | ␉}␊ |
469 | ␉␊ |
470 | ␉␊ |
471 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
472 | ␉␊ |
473 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
474 | ␉␊ |
475 | ␉replace_word(0x27A28086, 0x27AE8086, executable, zstream.total_out);␊ |
476 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
477 | ␉␊ |
478 | ␉␊ |
479 | ␉zstream.next_in = (UInt8*)executable;␊ |
480 | ␉//␉␉zstream.next_out = (UInt8*)((int)compressed_data<<1);␊ |
481 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
482 | ␉␊ |
483 | ␉zstream.avail_in = full_size;␊ |
484 | ␉zstream.avail_out = compressed_size;␊ |
485 | ␉zstream.zalloc = Z_NULL;␊ |
486 | ␉zstream.zfree = Z_NULL;␊ |
487 | ␉zstream.opaque = Z_NULL;␊ |
488 | ␉␊ |
489 | ␉␊ |
490 | ␉␊ |
491 | ␉// Recompress the eecutable␊ |
492 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
493 | ␉if (Z_OK != zlib_result) {␊ |
494 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
495 | ␉␉getc();␊ |
496 | ␉}␊ |
497 | ␉else ␊ |
498 | ␉{␊ |
499 | ␉␉zstream_inited = true;␊ |
500 | ␉}␊ |
501 | ␉␊ |
502 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
503 | ␉␊ |
504 | ␉if (zlib_result == Z_STREAM_END)␊ |
505 | ␉{␊ |
506 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
507 | ␉} ␊ |
508 | ␉else if (zlib_result == Z_OK)␊ |
509 | ␉{␊ |
510 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
511 | ␉␉ */␊ |
512 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
513 | ␉␉␊ |
514 | ␉} ␊ |
515 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
516 | ␉{␊ |
517 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
518 | ␉␉getc();␊ |
519 | ␉}␊ |
520 | ␉␊ |
521 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
522 | ␉␊ |
523 | ␉free(executable);␊ |
524 | ␉␊ |
525 | ␉return true;␉␊ |
526 | } |