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 "bootstruct.h"␊ |
15 | #include "pci.h"␊ |
16 | #include "drivers.h"␊ |
17 | #include "mkext.h"␊ |
18 | #include "modules.h"␊ |
19 | #include "hex_editor.h"␊ |
20 | ␊ |
21 | ␊ |
22 | #define kHDACodec␉␉␉␉"HDACodec"␊ |
23 | ␊ |
24 | ␊ |
25 | #ifndef DEBUG_KEXT_PATCHER␊ |
26 | #define DEBUG_KEXT_PATCHER 1␊ |
27 | #endif␊ |
28 | ␊ |
29 | #if DEBUG_KEXT_PATCHER␊ |
30 | #define DBG(x...)␉printf(x)␊ |
31 | #else␊ |
32 | #define DBG(x...)␊ |
33 | #endif␊ |
34 | ␊ |
35 | ␊ |
36 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
37 | bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
38 | bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start);␊ |
39 | ␊ |
40 | ␊ |
41 | ␊ |
42 | static void * z_alloc(void *, u_int items, u_int size);␊ |
43 | static void z_free(void *, void *ptr);␊ |
44 | ␊ |
45 | #if UNUSED␊ |
46 | void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6);␊ |
47 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start);␊ |
48 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
49 | int chartohex(char c);␊ |
50 | uint16_t patch_gma_deviceid = 0;␊ |
51 | uint16_t patch_bcm_deviceid = 0;␊ |
52 | // TODO: add detection code / a method for users to enter the id␊ |
53 | uint16_t patch_hda_codec = 0;␊ |
54 | ␊ |
55 | #define NEEDS_PATCHING␉␉(patch_bcm_deviceid || patch_gma_deviceid || patch_hda_codec)␊ |
56 | #endif␊ |
57 | ␊ |
58 | typedef struct z_mem {␊ |
59 | uint32_t alloc_size;␊ |
60 | uint8_t data[0];␊ |
61 | } z_mem;␊ |
62 | ␊ |
63 | /*␊ |
64 | * Space allocation and freeing routines for use by zlib routines.␊ |
65 | */␊ |
66 | void *␊ |
67 | z_alloc(void * notused __unused, u_int num_items, u_int size)␊ |
68 | {␊ |
69 | void * result = NULL;␊ |
70 | z_mem * zmem = NULL;␊ |
71 | uint32_t total = num_items * size;␊ |
72 | uint32_t allocSize = total + sizeof(zmem);␊ |
73 | ␊ |
74 | zmem = (z_mem *)malloc(allocSize);␊ |
75 | if (!zmem) {␊ |
76 | goto finish;␊ |
77 | }␊ |
78 | zmem->alloc_size = allocSize;␊ |
79 | result = (void *)&(zmem->data);␊ |
80 | finish:␊ |
81 | return result;␊ |
82 | }␊ |
83 | ␊ |
84 | void␊ |
85 | z_free(void * notused __unused, void * ptr)␊ |
86 | {␊ |
87 | uint32_t * skipper = (uint32_t *)ptr - 1;␊ |
88 | z_mem * zmem = (z_mem *)skipper;␊ |
89 | free((void *)zmem);␊ |
90 | return;␊ |
91 | }␊ |
92 | ␊ |
93 | ␊ |
94 | //unsigned long Mkext_Alder32( unsigned char * buffer, long length );␊ |
95 | static unsigned long␊ |
96 | Mkext_Alder32( unsigned char * buffer, long length )␊ |
97 | {␊ |
98 | long cnt;␊ |
99 | unsigned long result, lowHalf, highHalf;␊ |
100 | ␊ |
101 | lowHalf = 1;␊ |
102 | highHalf = 0;␊ |
103 | ␉␊ |
104 | ␉for ( cnt = 0; cnt < length; cnt++ )␊ |
105 | {␊ |
106 | if ((cnt % 5000) == 0)␊ |
107 | {␊ |
108 | lowHalf %= 65521L;␊ |
109 | highHalf %= 65521L;␊ |
110 | }␊ |
111 | ␉␉␊ |
112 | lowHalf += buffer[cnt];␊ |
113 | highHalf += lowHalf;␊ |
114 | }␊ |
115 | ␉␊ |
116 | ␉lowHalf %= 65521L;␊ |
117 | ␉highHalf %= 65521L;␊ |
118 | ␉␊ |
119 | ␉result = (highHalf << 16) | lowHalf;␊ |
120 | ␉␊ |
121 | ␉return result;␊ |
122 | }␊ |
123 | ␊ |
124 | /**␊ |
125 | ** KextPatcher_start -> module start␊ |
126 | **␉␉Notified the module system that this module will hook into the ␊ |
127 | **␉␉LoadMatchedModules and LoadDriverMKext functions␊ |
128 | **/␊ |
129 | void KextPatcher_start()␊ |
130 | {␉␉␊ |
131 | ␉// Hooks into the following:␊ |
132 | ␉//␉execute_hook("LoadDriverMKext", (void*)package, &length, NULL, NULL, NULL, NULL);␊ |
133 | ␉// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL, NULL, NULL);␊ |
134 | #if UNUSED␊ |
135 | ␉register_hook_callback("PCIDevice", &KextPatcher_hook);␊ |
136 | #endif␊ |
137 | ␉//register_hook_callback("LoadMatchedModules", &kext_loaded); ␊ |
138 | ␉register_hook_callback("LoadDriverMKext", &mkext_loaded); ␊ |
139 | ␊ |
140 | }␊ |
141 | ␊ |
142 | /**␊ |
143 | ** kext_loaded -> Called whenever a kext is in read into memory␊ |
144 | **␉␉This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)␊ |
145 | **␉␉and their plists when they are loaded into memmory␊ |
146 | **/␊ |
147 | void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg4, void* arg5, void* arg6)␊ |
148 | {␊ |
149 | ␉␊ |
150 | ␉//ModulePtr module = moduletmp;␊ |
151 | ␉//long length = *(long*)lengthprt;␊ |
152 | ␉//long length2 = strlen(module->plistAddr);␊ |
153 | ␉// *(long*)lengthprt = length2 + 5 * 1024 * 1024;␊ |
154 | ␊ |
155 | ␉//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);␊ |
156 | ␉//getc();␊ |
157 | }␊ |
158 | ␊ |
159 | /**␊ |
160 | ** mkext_loaded -> Called whenever an mkext is in read into memory␊ |
161 | **␉␉This function will be used to patch mkext. Matching kexts will be␊ |
162 | **␉␉Extracted, modified, and then compressed again. Note: I need to determine␊ |
163 | **␉␉what sort of slowdown this will cause and if it's worth implimenting.␊ |
164 | **/␊ |
165 | ␊ |
166 | void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg4, void* arg5, void* arg6)␊ |
167 | {␊ |
168 | #if UNUSED␊ |
169 | ␉const char* hda_codec;␊ |
170 | ␉int len = 0;␊ |
171 | ␉␊ |
172 | ␉if (getValueForKey(kHDACodec, &hda_codec, &len, DEFAULT_BOOT_CONFIG))␊ |
173 | ␉{␊ |
174 | ␉␉int index = 0;␊ |
175 | ␉␉while(len)␊ |
176 | ␉␉{␊ |
177 | ␉␉␉patch_hda_codec <<= 4;␊ |
178 | ␉␉␉patch_hda_codec |= chartohex(hda_codec[index]);␊ |
179 | ␉␉␉len--;␊ |
180 | ␉␉␉index++;␊ |
181 | ␉␉}␊ |
182 | ␉}␊ |
183 | ␉␉␊ |
184 | ␉if(!NEEDS_PATCHING) return;␉// No need to apply a patch, hardware doesn't need it␊ |
185 | #endif␉␊ |
186 | ␉int version = 0;␊ |
187 | ␉//int length = *((int*)lengthtmp);␊ |
188 | ␉mkext_basic_header* package = (mkext_basic_header*)packagetmp;␊ |
189 | ␊ |
190 | ␉// Verify the MKext.␊ |
191 | if (( MKEXT_GET_MAGIC(package)␉␉!= MKEXT_MAGIC ) ||␊ |
192 | ( MKEXT_GET_SIGNATURE(package)␉!= MKEXT_SIGN ) ||␊ |
193 | ( MKEXT_GET_LENGTH(package)␉␉> kLoadSize )␉ ||␊ |
194 | ( MKEXT_GET_CHECKSUM(package) !=␊ |
195 | ␉␉ Mkext_Alder32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )␊ |
196 | {␊ |
197 | ␉␉return;␊ |
198 | ␉␉// Don't try to patch a b␊ |
199 | }␉␊ |
200 | ␉␉␊ |
201 | ␉/*␊ |
202 | ␉if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0)␊ |
203 | ␉{␊ |
204 | ␉␉printf("Invalidating mkext %s\n", filespec);␊ |
205 | ␉␉// 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it.␊ |
206 | ␉␉//package->adler32++;␊ |
207 | ␉␉// NOTE: double check that this is needed␊ |
208 | ␉␉package->magic = 0x00;␊ |
209 | ␉␉return;␊ |
210 | ␉}*/␊ |
211 | ␉␊ |
212 | ␉␊ |
213 | ␉version = MKEXT_GET_VERSION(package);␊ |
214 | ␉␊ |
215 | ␉if(version == 0x01008000) // mkext1␊ |
216 | ␉{␊ |
217 | ␉␉// mkext1 uses lzss␊ |
218 | ␉␉mkext1_header* package = (mkext1_header*)packagetmp;␊ |
219 | ␉␉int i;␊ |
220 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
221 | ␉␉{␊ |
222 | ␉␉␉DBG("Parsing kext %d\n", i);␊ |
223 | ␉␉␉//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);␊ |
224 | ␉␉␉// uses decompress_lzss␊ |
225 | ␉␉␉// TODO: handle kext␊ |
226 | ␊ |
227 | ␉␉}␊ |
228 | ␉}␊ |
229 | ␉else if((version & 0xFFFF0000) == 0x02000000) // mkext2␊ |
230 | ␉{␉␉␊ |
231 | ␉␉// mkext2 uses zlib␉␉␊ |
232 | ␉␉mkext2_header* package = (mkext2_header*)packagetmp;␊ |
233 | ␉␉z_stream zstream;␊ |
234 | ␉␉bool zstream_inited = false;␊ |
235 | ␉␉int zlib_result;␊ |
236 | ␉␉int plist_offset = MKEXT2_GET_PLIST(package);␊ |
237 | ␉␉␊ |
238 | ␉␉char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
239 | ␉␉␊ |
240 | ␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
241 | ␉␉zstream.next_in = (UInt8*)((char*)package + plist_offset);␊ |
242 | ␉␉zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
243 | ␉␉␊ |
244 | ␉␉zstream.next_out = (UInt8*)plist;␊ |
245 | ␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
246 | ␉␉␊ |
247 | ␉␉zstream.zalloc = z_alloc;␊ |
248 | ␉␉zstream.zfree = z_free;␊ |
249 | ␉␉␉␉␉␉␉␉␊ |
250 | ␉␉zlib_result = inflateInit(&zstream);␊ |
251 | ␉␉if (Z_OK != zlib_result)␊ |
252 | ␉␉{␊ |
253 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
254 | ␉␉␉getc();␊ |
255 | ␉␉}␊ |
256 | ␉␉else ␊ |
257 | ␉␉{␊ |
258 | ␉␉␉zstream_inited = true;␊ |
259 | ␉␉}␊ |
260 | ␊ |
261 | ␉␉␊ |
262 | ␉␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
263 | ␉␉if (zstream_inited) inflateEnd(&zstream);␊ |
264 | ␊ |
265 | ␉␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);␊ |
266 | ␉␉␊ |
267 | ␉␉if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)␊ |
268 | ␉␉{␉␉␉␊ |
269 | ␉␉␉config_file_t plistData;␊ |
270 | ␉␉␉config_file_t allDicts;␊ |
271 | ␉␉␉bzero(&plistData, sizeof(plistData));␊ |
272 | ␉␉␉bzero(&allDicts, sizeof(allDicts));␊ |
273 | ␉␉␉␊ |
274 | ␉␉␉XMLParseFile( plist, &plistData.dictionary );␊ |
275 | ␊ |
276 | ␉␉␉int count = 0;␊ |
277 | ␊ |
278 | ␉␉␉allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey);␊ |
279 | ␉␉␉count = XMLTagCount(allDicts.dictionary);␊ |
280 | ␊ |
281 | ␉␉␉DBG("Plist contains %d kexts\n", count);␉␉␉␊ |
282 | ␉␉␉␉␉␉␊ |
283 | ␉␉␉bool patched = false;␊ |
284 | ␉␉␉␊ |
285 | ␉␉␉for(; count > 0 ;count-- )␊ |
286 | ␉␉␉{␊ |
287 | ␉␉␉␉TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count);␊ |
288 | ␉␉␉␉patched |= patch_kext(kextEntry, plist, package);␊ |
289 | ␉␉␉}␊ |
290 | ␉␉␉␉␉␉␊ |
291 | ␉␉␉if(patched)␊ |
292 | ␉␉␉{␉␉␉␉␊ |
293 | ␉␉␉␉zstream_inited = false;␊ |
294 | ␉␉␉␉// Recompress the plist␊ |
295 | ␉␉␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
296 | ␉␉␉␉zstream.next_in = (UInt8*)plist;␊ |
297 | ␉␉␉␉zstream.next_out = (UInt8*)package + plist_offset;␊ |
298 | ␉␉␉␉zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
299 | ␉␉␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2;␉// Give us some extra free space, just in case␊ |
300 | ␉␉␉␉zstream.zalloc = Z_NULL;␊ |
301 | ␉␉␉␉zstream.zfree = Z_NULL;␊ |
302 | ␉␉␉␉zstream.opaque = Z_NULL;␊ |
303 | ␉␉␉␉␊ |
304 | ␉␉␉␉␊ |
305 | ␉␉␉␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
306 | ␉␉␉␉if (Z_OK != zlib_result) {␊ |
307 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
308 | ␉␉␉␉␉getc();␊ |
309 | ␉␉␉␉}␊ |
310 | ␉␉␉␉else ␊ |
311 | ␉␉␉␉{␊ |
312 | ␉␉␉␉␉zstream_inited = true;␊ |
313 | ␉␉␉␉}␊ |
314 | ␉␉␉␉␊ |
315 | ␉␉␉␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
316 | ␉␉␉␉␊ |
317 | ␉␉␉␉if (zlib_result == Z_STREAM_END)␊ |
318 | ␉␉␉␉{␊ |
319 | ␉␉␉␉␉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));␊ |
320 | ␉␉␉␉␉␊ |
321 | ␉␉␉␉} ␊ |
322 | ␉␉␉␉else if (zlib_result == Z_OK)␊ |
323 | ␉␉␉␉{␊ |
324 | ␉␉␉␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
325 | ␉␉␉␉␉ */␊ |
326 | ␉␉␉␉␉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));␊ |
327 | ␉␉␉␉␉␊ |
328 | ␉␉␉␉} ␊ |
329 | ␉␉␉␉else if (zlib_result != Z_STREAM_ERROR)␊ |
330 | ␉␉␉␉{␊ |
331 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
332 | ␉␉␉␉␉getc();␊ |
333 | ␉␉␉␉}␊ |
334 | ␉␉␉␉␊ |
335 | ␉␉␉␉if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package))␊ |
336 | ␉␉␉␉{␊ |
337 | ␉␉␉␉␉// Update the mkext length␊ |
338 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out);␊ |
339 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
340 | ␉␉␉␉␉*((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
341 | ␉␉␉␉␉*((int*)lengthtmp) += zstream.total_out;␊ |
342 | ␉␉␉␉}␊ |
343 | ␉␉␉␉␉␉␉␉␊ |
344 | ␉␉␉␉if (zstream_inited) deflateEnd(&zstream);␊ |
345 | ␉␉␉␉␊ |
346 | ␉␉␉␉␊ |
347 | ␉␉␉␉␊ |
348 | ␉␉␉␉// re alder32 the new mkext2 package␊ |
349 | ␉␉␉␉MKEXT_HDR_CAST(package)->adler32 = ␊ |
350 | ␉␉␉␉␉MKEXT_SWAP(Mkext_Alder32((unsigned char *)&package->version,␊ |
351 | ␉␉␉␉␉␉␉␉␉␉␉ MKEXT_GET_LENGTH(package) - 0x10));␊ |
352 | ␉␉␉␉ ␊ |
353 | ␉␉␉}␊ |
354 | ␉␉}␊ |
355 | ␉␉else␊ |
356 | ␉␉{␊ |
357 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
358 | ␉␉␉getc();␊ |
359 | ␉␉}␉␉␊ |
360 | ␊ |
361 | ␉}␉␊ |
362 | ␉␊ |
363 | }␊ |
364 | ␊ |
365 | // FIXME: only handles mkext2 entries␊ |
366 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
367 | {␊ |
368 | ␉␊ |
369 | ␉char* bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));␊ |
370 | ␉␉␉␊ |
371 | ␉if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) ␊ |
372 | ␉{␉␊ |
373 | ␉␉printf("Kext is plist only, aka legacykext\n");␉␉␊ |
374 | ␉␉return false;␉// Kext is a plist only kext, don't patch␊ |
375 | ␉}␉␊ |
376 | ␉␊ |
377 | #if UNUSED␊ |
378 | ␉if(/*patch_gma_deviceid &&*/␊ |
379 | ␉ (␊ |
380 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||␊ |
381 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)␊ |
382 | ␉␉ )␊ |
383 | ␉ )␊ |
384 | ␉{␊ |
385 | ␉␉/*if(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0 || patch_gma_deviceid == 0x27ae)␊ |
386 | ␉␉{␊ |
387 | ␉␉␉return patch_gma_kexts(plist, plistbuffer, start);␊ |
388 | ␉␉}␊ |
389 | ␉␉else␊ |
390 | ␉␉{␊ |
391 | ␉␉␉␊ |
392 | ␉␉}*/␊ |
393 | ␉␉printf("%s found \n", bundleID);␊ |
394 | ␉␉␊ |
395 | ␉}␊ |
396 | ␉else if(/*patch_bcm_deviceid &&*/ (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0))␊ |
397 | ␉{␉␉␊ |
398 | ␉␉␊ |
399 | ␉␉//return patch_bcm_kext(plist, plistbuffer, start);␊ |
400 | ␊ |
401 | ␉}␊ |
402 | ␉else if(/*patch_bcm_deviceid &&*/ (strcmp(bundleID, "com.apple.iokit.IOAHCIBlockStorage") == 0))␊ |
403 | ␉{␉␉␊ |
404 | ␉␉␊ |
405 | ␉}␊ |
406 | ␉else ␊ |
407 | #endif␊ |
408 | ␉if(/*patch_hda_codec && */strcmp(bundleID, "com.apple.driver.AppleHDA") == 0)␊ |
409 | ␉{␊ |
410 | ␉␉//it seems that applehda.kext is not in extensions.mkext␊ |
411 | ␉␉return patch_hda_kext(plist, plistbuffer, start);␊ |
412 | ␊ |
413 | ␉}␉␉␊ |
414 | ␉else if(/*patch_hda_codec &&*/strcmp(bundleID, "com.apple.driver.AppleHDAController") == 0)␊ |
415 | ␉{␊ |
416 | ␉␉␊ |
417 | ␉␉//return patch_hda_controller(plist, plistbuffer, start);␊ |
418 | ␊ |
419 | ␉}␊ |
420 | ␉␊ |
421 | ␉return false;␊ |
422 | }␊ |
423 | ␊ |
424 | #if UNUSED␊ |
425 | void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␊ |
426 | {␊ |
427 | ␉pci_dt_t* current = arg1;␊ |
428 | ␉if(current)␊ |
429 | ␉{␊ |
430 | ␉␉switch(current->class_id)␊ |
431 | ␉␉{␊ |
432 | ␉␉␉case PCI_CLASS_MULTIMEDIA_AUDIO:␊ |
433 | ␉␉␉␉break;␊ |
434 | ␉␉␉␉␊ |
435 | ␉␉␉case PCI_CLASS_DISPLAY_VGA:␊ |
436 | ␉␉␉␉if(current->vendor_id == 0x8086 && ␊ |
437 | ␉␉␉␉ (␊ |
438 | ␉␉␉␉␉current->device_id == 0x27AE ||␊ |
439 | ␉␉␉␉␉current->device_id == 0xA001 ||␊ |
440 | ␉␉␉␉␉current->device_id == 0xA002 ||␊ |
441 | ␉␉␉␉␉current->device_id == 0xA011 ||␊ |
442 | ␉␉␉␉␉current->device_id == 0xA012␊ |
443 | ␊ |
444 | ␉␉␉␉␉)␊ |
445 | ␉␉␉␉ )␊ |
446 | ␉␉␉␉{␊ |
447 | ␉␉␉␉␉patch_gma_deviceid = current->device_id;␊ |
448 | ␉␉␉␉}␊ |
449 | ␉␉␉␉break;␊ |
450 | ␉␉␉␉␊ |
451 | ␉␉␉case PCI_CLASS_NETWORK_OTHER:␊ |
452 | ␉␉␉␉␊ |
453 | ␉␉␉␉// Patch BCM43xx␊ |
454 | ␉␉␉␉if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300))␊ |
455 | ␉␉␉␉{␊ |
456 | ␉␉␉␉␉patch_bcm_deviceid = current->device_id;␊ |
457 | ␉␉␉␉}␊ |
458 | ␉␉␉␉break;␉␉␉␊ |
459 | ␉␉␉default:␊ |
460 | ␉␉␉␉break;␊ |
461 | ␉␉}␊ |
462 | ␉}␊ |
463 | }␊ |
464 | #endif␊ |
465 | ␊ |
466 | ␊ |
467 | bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start)␊ |
468 | {␊ |
469 | ␉return false;␊ |
470 | ␉// change the PCI class code to match to. Note: A LegacyHDA plist should do this on it's own␊ |
471 | ␉// As such, it's disabled␊ |
472 | ␊ |
473 | ␉// TODO: read class code␊ |
474 | ␉TagPtr personality;␊ |
475 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
476 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"BuiltInHDA");␉␊ |
477 | ␉TagPtr match_class =XMLCastArray(XMLGetProperty(personality, (const char*)"IOPCIClassMatch"));␊ |
478 | ␉␊ |
479 | ␉␊ |
480 | ␉char* new_str = malloc(strlen("0xXXXX000&0xFFFE0000")+1);␊ |
481 | ␉snprintf(new_str, strlen("0xXXXX000&0xFFFE0000")+1,"0x04030000&0xFFFE0000"); // todo, pass in actual class id␊ |
482 | ␉␊ |
483 | ␉␊ |
484 | ␉char* orig_string = "0x04020000&0xFFFE0000"; //XMLCastString(match_class);␊ |
485 | ␉␊ |
486 | ␉DBG("Attemting to replace '%s' with '%s'\n", orig_string, new_str);␊ |
487 | ␉␊ |
488 | ␉// TODO: verify string doesn't exist first.␊ |
489 | ␉␊ |
490 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(match_class), 10240);␊ |
491 | ␉␊ |
492 | ␉return true;␊ |
493 | ␉␊ |
494 | }␊ |
495 | ␊ |
496 | bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
497 | {␉␊ |
498 | ␉␊ |
499 | ␉␊ |
500 | ␉int full_size, compressed_size, executable_offset;␊ |
501 | ␉void* compressed_data;␊ |
502 | ␉mkext2_file_entry* kext;␊ |
503 | ␉int zlib_result;␊ |
504 | ␉z_stream zstream;␊ |
505 | ␉bool zstream_inited = false;␊ |
506 | #if UNUSED␊ |
507 | ␉uint16_t find_codec = 0;␊ |
508 | ␉switch(0xFF00 & patch_hda_codec)␊ |
509 | ␉{␊ |
510 | ␉␉case 0x0200:␊ |
511 | ␉␉␉find_codec = 0x0262;␊ |
512 | ␉␉␉break;␊ |
513 | ␊ |
514 | ␉␉case 0x0800:␊ |
515 | ␉␉␉find_codec = 0x0885;␊ |
516 | ␉␉␉break;␊ |
517 | ␉␉␉␊ |
518 | ␉␉case 0x0600:␉// specificaly the 662␊ |
519 | ␉␉␉find_codec = 0x0885;␊ |
520 | ␉␉␉break;␊ |
521 | ␉}␊ |
522 | ␉␊ |
523 | ␉if(!find_codec) return false;␉// notify caller that we aren't patching the kext␊ |
524 | #endif␊ |
525 | ␉␉␊ |
526 | ␉executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
527 | ␉kext = (void*)((char*)start + executable_offset);␊ |
528 | ␊ |
529 | ␉full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
530 | ␉compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
531 | ␉compressed_data = MKEXT2_GET_ENTRY_DATA(kext);␉␊ |
532 | ␉executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
533 | ␉␊ |
534 | ␉␊ |
535 | ␉char* executable = malloc(full_size);␊ |
536 | ␉␊ |
537 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
538 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
539 | ␉zstream.avail_in = compressed_size;␊ |
540 | ␉␊ |
541 | ␉zstream.next_out = (UInt8*)executable;␊ |
542 | ␉zstream.avail_out = full_size;␊ |
543 | ␉␊ |
544 | ␉zstream.zalloc = z_alloc;␊ |
545 | ␉zstream.zfree = z_free;␊ |
546 | ␉␊ |
547 | ␉zlib_result = inflateInit(&zstream);␊ |
548 | ␉if (Z_OK != zlib_result)␊ |
549 | ␉{␊ |
550 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
551 | ␉␉getc();␊ |
552 | ␉}␊ |
553 | ␉else ␊ |
554 | ␉{␊ |
555 | ␉␉zstream_inited = true;␊ |
556 | ␉}␊ |
557 | ␉␊ |
558 | ␉␊ |
559 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
560 | ␉␊ |
561 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
562 | ␉␉␊ |
563 | #if UNUSED␊ |
564 | ␉replace_word(0x10EC | (find_codec << 16), 0x10EC | (patch_hda_codec << 16), executable, zstream.total_out);␊ |
565 | #else␊ |
566 | ␉if ((replace_word(0x10EC | (0x0885 << 16), 0x10EC | (0x0888 << 16), executable, zstream.total_out)) == 0)␊ |
567 | ␉{␊ |
568 | ␉␉if (zstream_inited) inflateEnd(&zstream);␊ |
569 | ␉␉free(executable);␊ |
570 | ␉␉return false;␊ |
571 | ␉}␊ |
572 | #endif␊ |
573 | ␉␊ |
574 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
575 | ␉␊ |
576 | ␉␊ |
577 | ␉zstream.next_in = (UInt8*)executable;␊ |
578 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
579 | ␉␊ |
580 | ␉zstream.avail_in = full_size;␊ |
581 | ␉zstream.avail_out = compressed_size;␊ |
582 | ␉zstream.zalloc = Z_NULL;␊ |
583 | ␉zstream.zfree = Z_NULL;␊ |
584 | ␉zstream.opaque = Z_NULL;␊ |
585 | ␉␊ |
586 | ␉␊ |
587 | ␉␊ |
588 | ␉// Recompress the eecutable␊ |
589 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
590 | ␉if (Z_OK != zlib_result) {␊ |
591 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
592 | ␉␉getc();␊ |
593 | ␉}␊ |
594 | ␉else ␊ |
595 | ␉{␊ |
596 | ␉␉zstream_inited = true;␊ |
597 | ␉}␊ |
598 | ␉␊ |
599 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
600 | ␉␊ |
601 | ␉if (zlib_result == Z_STREAM_END)␊ |
602 | ␉{␊ |
603 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
604 | ␉␉getc();␊ |
605 | ␉} ␊ |
606 | ␉else if (zlib_result == Z_OK)␊ |
607 | ␉{␊ |
608 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
609 | ␉␉ */␊ |
610 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
611 | ␉␉getc();␊ |
612 | ␉} ␊ |
613 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
614 | ␉{␊ |
615 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
616 | ␉␉getc();␊ |
617 | ␉}␊ |
618 | ␉␊ |
619 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
620 | ␉␊ |
621 | ␉free(executable);␊ |
622 | ␉␊ |
623 | ␉return true;␉␊ |
624 | ␊ |
625 | }␊ |
626 | #if UNUSED␊ |
627 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
628 | {␊ |
629 | ␉TagPtr personality;␊ |
630 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
631 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"Broadcom 802.11 PCI");␉␊ |
632 | ␉TagPtr match_names =XMLCastArray(XMLGetProperty(personality, (const char*)"IONameMatch"));␊ |
633 | ␊ |
634 | ␉␊ |
635 | ␉char* new_str = malloc(strlen("pci14e4,xxxx")+1);␊ |
636 | ␉snprintf(new_str, strlen("pci14e4,xxxx")+1,"pci14e4,%02x", patch_bcm_deviceid);␊ |
637 | ␊ |
638 | ␉// Check to see if we *really* need to modify the plist, if not, return false␊ |
639 | ␉// so that *if* this were going ot be the only modified kext, the repacking code␊ |
640 | ␉// won't need to be executed.␊ |
641 | ␉int count = XMLTagCount(match_names);␊ |
642 | ␉while(count)␊ |
643 | ␉{␊ |
644 | ␉␉count--;␊ |
645 | ␉␉TagPtr replace =␉XMLGetElement(match_names, count);␉// Modify the second entry␊ |
646 | ␉␉char* orig_string = XMLCastString(replace);␊ |
647 | ␉␉if(strcmp(orig_string, new_str) == 0) return false;␊ |
648 | ␉}␊ |
649 | ␊ |
650 | ␉␊ |
651 | ␉TagPtr replace =␉XMLGetElement(match_names, 1);␉// Modify the second entry␊ |
652 | ␉char* orig_string = XMLCastString(replace);␊ |
653 | ␉␊ |
654 | ␉␊ |
655 | ␉// TODO: verify string doesn't exist first.␊ |
656 | ␉␊ |
657 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(replace), 10240);␊ |
658 | ␊ |
659 | ␉return true;␊ |
660 | }␊ |
661 | ␊ |
662 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start)␊ |
663 | {␊ |
664 | ␉// TODO: clean up this function / split into two / etc␊ |
665 | ␉int exeutable_offset, full_size, compressed_size;␊ |
666 | ␉TagPtr personality;␊ |
667 | ␉long offset;␊ |
668 | ␉int zlib_result;␊ |
669 | ␉z_stream zstream;␊ |
670 | ␉bool zstream_inited = false;␊ |
671 | ␉mkext2_file_entry* kext;␊ |
672 | ␉void* compressed_data;␊ |
673 | ␊ |
674 | ␉exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
675 | ␉kext = (void*)((char*)start + exeutable_offset);␊ |
676 | ␊ |
677 | ␉full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
678 | ␉compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
679 | ␉compressed_data = MKEXT2_GET_ENTRY_DATA(kext);␊ |
680 | ␉␊ |
681 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
682 | ␉␊ |
683 | ␉␊ |
684 | ␉␊ |
685 | ␉char* executable = malloc(full_size);␊ |
686 | ␉␊ |
687 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
688 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
689 | ␉zstream.avail_in = compressed_size;␊ |
690 | ␉␊ |
691 | ␉zstream.next_out = (UInt8*)executable;␊ |
692 | ␉zstream.avail_out = full_size;␊ |
693 | ␉␊ |
694 | ␉zstream.zalloc = z_alloc;␊ |
695 | ␉zstream.zfree = z_free;␊ |
696 | ␉␊ |
697 | ␉zlib_result = inflateInit(&zstream);␊ |
698 | ␉if (Z_OK != zlib_result)␊ |
699 | ␉{␊ |
700 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
701 | ␉␉getc();␊ |
702 | ␉}␊ |
703 | ␉else ␊ |
704 | ␉{␊ |
705 | ␉␉zstream_inited = true;␊ |
706 | ␉}␊ |
707 | ␉␊ |
708 | ␉␊ |
709 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
710 | ␉␊ |
711 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
712 | ␉␊ |
713 | ␉␊ |
714 | ␉␊ |
715 | ␉if(XMLGetProperty(personality, (const char*)"Intel915"))␊ |
716 | ␉{␊ |
717 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"Intel915");␊ |
718 | ␉␉// IOAccelerator kext␊ |
719 | ␉}␊ |
720 | ␉else␊ |
721 | ␉{␊ |
722 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer");␊ |
723 | ␉␉// Framebuffer Kext␊ |
724 | ␉␉␊ |
725 | ␉␉if((patch_gma_deviceid & 0xFF00) == 0xA000)␉// GMA3150␊ |
726 | ␉␉{␊ |
727 | ␉␉␉// Cursor corruption fix.␊ |
728 | ␉␉␉// This patch changes the cursor address from␊ |
729 | ␉␉␉// a physical address (used in the gma950) to an offset (used in the gma3150).␊ |
730 | ␉␉␉␊ |
731 | ␉␉␉char find_bytes[] = {0x8b, 0x55, 0x08, 0x83, 0xba, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x36, 0x89, 0x04, 0x24, 0xe8, 0x32, 0xbb, 0xff, 0xff};␉// getPhysicalAddress() and more␊ |
732 | ␉␉␉char new_bytes[] = {0xb8, 0x00, 0x00, 0x00, 0x02, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB, 0x04, 0x00, 0x00, 0x00, 0x00};␉// jump past getPhysicalAddress binding. NOTE: last six bytes are unusable␊ |
733 | ␉␉␉replace_bytes(find_bytes, sizeof(find_bytes), new_bytes, sizeof(new_bytes), executable, zstream.total_out);␊ |
734 | ␉␉}␊ |
735 | ␉␉␊ |
736 | ␉}␊ |
737 | ␉␊ |
738 | ␉␊ |
739 | #if DEBUG_KEXT_PATCHER␊ |
740 | ␉char* pcimatch =␉XMLCastString(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
741 | #endif␊ |
742 | ␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
743 | ␉␊ |
744 | ␉char* newstring = malloc(strlen("0x00008086") + 1);␊ |
745 | ␉snprintf(newstring, strlen("0x00008086") + 1,"0x%04x", 0x8086 | (patch_gma_deviceid << 16));␊ |
746 | ␉␊ |
747 | ␉DBG("Replacing %s with %s\n", "0x00008086", newstring); ␊ |
748 | ␉replace_string("0x27A28086", newstring, plistbuffer + offset, 10240);␊ |
749 | ␉replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out);␊ |
750 | ␊ |
751 | ␉␊ |
752 | ␉␊ |
753 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
754 | ␉␊ |
755 | ␉␊ |
756 | ␉zstream.next_in = (UInt8*)executable;␊ |
757 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
758 | ␉␊ |
759 | ␉zstream.avail_in = full_size;␊ |
760 | ␉zstream.avail_out = compressed_size;␊ |
761 | ␉zstream.zalloc = Z_NULL;␊ |
762 | ␉zstream.zfree = Z_NULL;␊ |
763 | ␉zstream.opaque = Z_NULL;␊ |
764 | ␉␊ |
765 | ␉␊ |
766 | ␉␊ |
767 | ␉// Recompress the eecutable␊ |
768 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
769 | ␉if (Z_OK != zlib_result) {␊ |
770 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
771 | ␉␉getc();␊ |
772 | ␉}␊ |
773 | ␉else ␊ |
774 | ␉{␊ |
775 | ␉␉zstream_inited = true;␊ |
776 | ␉}␊ |
777 | ␉␊ |
778 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
779 | ␉␊ |
780 | ␉if (zlib_result == Z_STREAM_END)␊ |
781 | ␉{␊ |
782 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
783 | ␉} ␊ |
784 | ␉else if (zlib_result == Z_OK)␊ |
785 | ␉{␊ |
786 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
787 | ␉␉ */␊ |
788 | ␉␉printf("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
789 | ␉␉printf("ERROR: Unable to compress patched kext, not enough room.\n");␊ |
790 | ␉␉pause();␊ |
791 | ␉␉␊ |
792 | ␉} ␊ |
793 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
794 | ␉{␊ |
795 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
796 | ␉␉getc();␊ |
797 | ␉}␊ |
798 | ␉//kext->compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
799 | ␊ |
800 | ␉␊ |
801 | ␉␊ |
802 | ␉␊ |
803 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
804 | ␉␊ |
805 | ␉free(executable);␊ |
806 | ␉␊ |
807 | ␉return true;␉␊ |
808 | }␊ |
809 | #endif␊ |
810 | ␊ |
811 | int chartohex(char c)␊ |
812 | {␊ |
813 | ␉if(c <= '9' && c >= '0')␊ |
814 | ␉{␊ |
815 | ␉␉return c - '0';␉// c is between 0 and 9␊ |
816 | ␉}␊ |
817 | ␉else if(c <= 'F' && c >= 'A')␊ |
818 | ␉{␊ |
819 | ␉␉return c - 'A' + 10; // c = 10 - 15;␊ |
820 | ␉}␊ |
821 | ␉else if(c <= 'f' && c >= 'a')␊ |
822 | ␉{␊ |
823 | ␉␉return c - 'a' + 10; // c = 10 - 15;␊ |
824 | ␉}␊ |
825 | ␉return 0;␊ |
826 | } |