Root/
Source at commit 610 created 13 years 6 months ago. By meklort, Added HDA patching capabilities. Currently disabled untill I add a way for either detection of a codec, or a way for users to specify the coedc | |
---|---|
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 | bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start);␊ |
34 | bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start);␊ |
35 | ␊ |
36 | static void * z_alloc(void *, u_int items, u_int size);␊ |
37 | static void z_free(void *, void *ptr);␊ |
38 | ␊ |
39 | uint16_t patch_gma_deviceid = 0;␊ |
40 | uint16_t patch_bcm_deviceid = 0;␊ |
41 | // TODO: add detection code / a method for users to enter the id␊ |
42 | uint16_t patch_hda_codec = 0;␊ |
43 | ␊ |
44 | #define NEEDS_PATCHING␉␉(patch_bcm_deviceid || patch_gma_deviceid | patch_hda_codec)␊ |
45 | ␊ |
46 | typedef struct z_mem {␊ |
47 | uint32_t alloc_size;␊ |
48 | uint8_t data[0];␊ |
49 | } z_mem;␊ |
50 | ␊ |
51 | /*␊ |
52 | * Space allocation and freeing routines for use by zlib routines.␊ |
53 | */␊ |
54 | void *␊ |
55 | z_alloc(void * notused __unused, u_int num_items, u_int size)␊ |
56 | {␊ |
57 | void * result = NULL;␊ |
58 | z_mem * zmem = NULL;␊ |
59 | uint32_t total = num_items * size;␊ |
60 | uint32_t allocSize = total + sizeof(zmem);␊ |
61 | ␊ |
62 | zmem = (z_mem *)malloc(allocSize);␊ |
63 | if (!zmem) {␊ |
64 | goto finish;␊ |
65 | }␊ |
66 | zmem->alloc_size = allocSize;␊ |
67 | result = (void *)&(zmem->data);␊ |
68 | finish:␊ |
69 | return result;␊ |
70 | }␊ |
71 | ␊ |
72 | void␊ |
73 | z_free(void * notused __unused, void * ptr)␊ |
74 | {␊ |
75 | uint32_t * skipper = (uint32_t *)ptr - 1;␊ |
76 | z_mem * zmem = (z_mem *)skipper;␊ |
77 | free((void *)zmem);␊ |
78 | return;␊ |
79 | }␊ |
80 | ␊ |
81 | ␊ |
82 | unsigned long Mkext_Alder32( unsigned char * buffer, long length );␊ |
83 | ␊ |
84 | void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4);␊ |
85 | ␊ |
86 | /**␊ |
87 | ** KextPatcher_start -> module start␊ |
88 | **␉␉Notified the module system that this module will hook into the ␊ |
89 | **␉␉LoadMatchedModules and LoadDriverMKext functions␊ |
90 | **/␊ |
91 | void KextPatcher_start()␊ |
92 | {␉␉␊ |
93 | ␉// Hooks into the following:␊ |
94 | ␉//␉execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL);␊ |
95 | ␉// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);␊ |
96 | ␊ |
97 | ␉register_hook_callback("PCIDevice", &KextPatcher_hook);␊ |
98 | ␉//register_hook_callback("LoadMatchedModules", &kext_loaded); ␊ |
99 | ␉register_hook_callback("LoadDriverMKext", &mkext_loaded); ␊ |
100 | ␊ |
101 | }␊ |
102 | ␊ |
103 | /**␊ |
104 | ** kext_loaded -> Called whenever a kext is in read into memory␊ |
105 | **␉␉This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)␊ |
106 | **␉␉and their plists when they are loaded into memmory␊ |
107 | **/␊ |
108 | void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3)␊ |
109 | {␊ |
110 | ␉␊ |
111 | ␉//ModulePtr module = moduletmp;␊ |
112 | ␉//long length = *(long*)lengthprt;␊ |
113 | ␉//long length2 = strlen(module->plistAddr);␊ |
114 | ␉// *(long*)lengthprt = length2 + 5 * 1024 * 1024;␊ |
115 | ␊ |
116 | ␉//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);␊ |
117 | ␉//getc();␊ |
118 | }␊ |
119 | ␊ |
120 | /**␊ |
121 | ** mkext_loaded -> Called whenever an mkext is in read into memory␊ |
122 | **␉␉This function will be used to patch mkext. Matching kexts will be␊ |
123 | **␉␉Extracted, modified, and then compressed again. Note: I need to determine␊ |
124 | **␉␉what sort of slowdown this will cause and if it's worth implimenting.␊ |
125 | **/␊ |
126 | ␊ |
127 | void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3)␊ |
128 | {␊ |
129 | ␉if(!NEEDS_PATCHING) return;␉// No need to apply a patch, hardware doesn't need it␊ |
130 | ␉␊ |
131 | ␉int version = 0;␊ |
132 | ␉//int length = *((int*)lengthtmp);␊ |
133 | ␉mkext_basic_header* package = packagetmp;␊ |
134 | ␊ |
135 | ␉// Verify the MKext.␊ |
136 | if (( MKEXT_GET_MAGIC(package)␉␉!= MKEXT_MAGIC ) ||␊ |
137 | ( MKEXT_GET_SIGNATURE(package)␉!= MKEXT_SIGN ) ||␊ |
138 | ( MKEXT_GET_LENGTH(package)␉␉> kLoadSize )␉ ||␊ |
139 | ( MKEXT_GET_CHECKSUM(package) !=␊ |
140 | ␉␉ Mkext_Alder32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )␊ |
141 | {␊ |
142 | return;␊ |
143 | ␉␉// Don't try to patch a b␊ |
144 | }␉␊ |
145 | ␉␊ |
146 | ␉/*␊ |
147 | ␉if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0)␊ |
148 | ␉{␊ |
149 | ␉␉printf("Invalidating mkext %s\n", filespec);␊ |
150 | ␉␉// 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it.␊ |
151 | ␉␉//package->adler32++;␊ |
152 | ␉␉// NOTE: double check that this is needed␊ |
153 | ␉␉package->magic = 0x00;␊ |
154 | ␉␉return;␊ |
155 | ␉}*/␊ |
156 | ␉␊ |
157 | ␉␊ |
158 | ␉version = MKEXT_GET_VERSION(package);␊ |
159 | ␉␊ |
160 | ␉if(version == 0x01008000) // mkext1␊ |
161 | ␉{␊ |
162 | ␉␉// mkext1 uses lzss␊ |
163 | ␉␉mkext1_header* package = packagetmp;␊ |
164 | ␉␉int i;␊ |
165 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
166 | ␉␉{␊ |
167 | ␉␉␉DBG("Parsing kext %d\n", i);␊ |
168 | ␉␉␉//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);␊ |
169 | ␉␉␉// uses decompress_lzss␊ |
170 | ␉␉␉// TODO: handle kext␊ |
171 | ␊ |
172 | ␉␉}␊ |
173 | ␉}␊ |
174 | ␉else if((version & 0xFFFF0000) == 0x02000000) // mkext2␊ |
175 | ␉{␊ |
176 | ␉␉DBG("Mkext2 package located at 0x%X\n", package);␊ |
177 | ␊ |
178 | ␉␉// mkext2 uses zlib␉␉␊ |
179 | ␉␉mkext2_header* package = packagetmp;␊ |
180 | ␉␉z_stream zstream;␊ |
181 | ␉␉bool zstream_inited = false;␊ |
182 | ␉␉int zlib_result;␊ |
183 | ␉␉int plist_offset = MKEXT2_GET_PLIST(package);␊ |
184 | ␉␉␊ |
185 | ␉␉char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
186 | ␉␉␊ |
187 | ␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
188 | ␉␉zstream.next_in = (UInt8*)((char*)package + plist_offset);␊ |
189 | ␉␉zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
190 | ␉␉␊ |
191 | ␉␉zstream.next_out = (UInt8*)plist;␊ |
192 | ␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
193 | ␉␉␊ |
194 | ␉␉zstream.zalloc = z_alloc;␊ |
195 | ␉␉zstream.zfree = z_free;␊ |
196 | ␉␉␉␉␊ |
197 | ␉␉zlib_result = inflateInit(&zstream);␊ |
198 | ␉␉if (Z_OK != zlib_result)␊ |
199 | ␉␉{␊ |
200 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
201 | ␉␉␉getc();␊ |
202 | ␉␉}␊ |
203 | ␉␉else ␊ |
204 | ␉␉{␊ |
205 | ␉␉␉zstream_inited = true;␊ |
206 | ␉␉}␊ |
207 | ␊ |
208 | ␉␉␊ |
209 | ␉␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
210 | ␉␉if (zstream_inited) inflateEnd(&zstream);␊ |
211 | ␊ |
212 | ␉␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);␊ |
213 | ␉␉if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)␊ |
214 | ␉␉{␉␉␉␊ |
215 | ␉␉␉config_file_t plistData;␊ |
216 | ␉␉␉config_file_t allDicts;␊ |
217 | ␉␉␉bzero(&plistData, sizeof(plistData));␊ |
218 | ␉␉␉bzero(&allDicts, sizeof(allDicts));␊ |
219 | ␉␉␉␊ |
220 | ␉␉␉XMLParseFile( plist, &plistData.dictionary );␊ |
221 | ␊ |
222 | ␉␉␉int count = 0;␊ |
223 | ␊ |
224 | ␉␉␉allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey);␊ |
225 | ␉␉␉count = XMLTagCount(allDicts.dictionary);␊ |
226 | ␊ |
227 | ␉␉␉DBG("Plist contains %d kexts\n", count);␊ |
228 | ␉␉␉␊ |
229 | ␉␉␉␊ |
230 | ␉␉␉bool patched = false;␊ |
231 | ␉␉␉for(; count--; count > 0)␊ |
232 | ␉␉␉{␊ |
233 | ␉␉␉␉TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count);␊ |
234 | ␉␉␉␉patched |= patch_kext(kextEntry, plist, package);␊ |
235 | ␉␉␉}␊ |
236 | ␉␉␉␊ |
237 | ␊ |
238 | ␉␉␉if(patched)␊ |
239 | ␉␉␉{␊ |
240 | ␉␉␉␉zstream_inited = false;␊ |
241 | ␉␉␉␉// Recompress the plist␊ |
242 | ␉␉␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
243 | ␉␉␉␉zstream.next_in = (UInt8*)plist;␊ |
244 | ␉␉␉␉zstream.next_out = (UInt8*)package + plist_offset;␊ |
245 | ␉␉␉␉zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
246 | ␉␉␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2;␉// Give us some extra free space, just in case␊ |
247 | ␉␉␉␉zstream.zalloc = Z_NULL;␊ |
248 | ␉␉␉␉zstream.zfree = Z_NULL;␊ |
249 | ␉␉␉␉zstream.opaque = Z_NULL;␊ |
250 | ␉␉␉␉␊ |
251 | ␉␉␉␉␊ |
252 | ␉␉␉␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
253 | ␉␉␉␉if (Z_OK != zlib_result) {␊ |
254 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
255 | ␉␉␉␉␉getc();␊ |
256 | ␉␉␉␉}␊ |
257 | ␉␉␉␉else ␊ |
258 | ␉␉␉␉{␊ |
259 | ␉␉␉␉␉zstream_inited = true;␊ |
260 | ␉␉␉␉}␊ |
261 | ␉␉␉␉␊ |
262 | ␉␉␉␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
263 | ␉␉␉␉␊ |
264 | ␉␉␉␉if (zlib_result == Z_STREAM_END)␊ |
265 | ␉␉␉␉{␊ |
266 | ␉␉␉␉␉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));␊ |
267 | ␉␉␉␉} ␊ |
268 | ␉␉␉␉else if (zlib_result == Z_OK)␊ |
269 | ␉␉␉␉{␊ |
270 | ␉␉␉␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
271 | ␉␉␉␉␉ */␊ |
272 | ␉␉␉␉␉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));␊ |
273 | ␉␉␉␉␉␊ |
274 | ␉␉␉␉} ␊ |
275 | ␉␉␉␉else if (zlib_result != Z_STREAM_ERROR)␊ |
276 | ␉␉␉␉{␊ |
277 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
278 | ␉␉␉␉␉getc();␊ |
279 | ␉␉␉␉}␊ |
280 | ␉␉␉␉␊ |
281 | ␉␉␉␉if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package))␊ |
282 | ␉␉␉␉{␊ |
283 | ␉␉␉␉␉// Update the mkext length␊ |
284 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out);␊ |
285 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
286 | ␉␉␉␉␉*((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
287 | ␉␉␉␉␉*((int*)lengthtmp) += zstream.total_out;␊ |
288 | ␉␉␉␉}␊ |
289 | ␉␉␉␉␉␉␉␉␊ |
290 | ␉␉␉␉if (zstream_inited) deflateEnd(&zstream);␊ |
291 | ␉␉␉␉␊ |
292 | ␉␉␉␉␊ |
293 | ␉␉␉␉␊ |
294 | ␉␉␉␉// re alder32 the new mkext2 package␊ |
295 | ␉␉␉␉MKEXT_HDR_CAST(package)->adler32 = ␊ |
296 | ␉␉␉␉␉MKEXT_SWAP(Mkext_Alder32((unsigned char *)&package->version,␊ |
297 | ␉␉␉␉␉␉␉␉␉␉␉ MKEXT_GET_LENGTH(package) - 0x10));␊ |
298 | ␉␉␉}␊ |
299 | ␉␉}␊ |
300 | ␉␉else␊ |
301 | ␉␉{␊ |
302 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
303 | ␉␉␉getc();␊ |
304 | ␉␉}␊ |
305 | ␊ |
306 | ␉␉//config_file_t mkextPlist;␊ |
307 | ␉␉//ParseXMLFile((char*) plist, &mkextPlist.dictionary);␊ |
308 | ␉␉␊ |
309 | ␉␉␊ |
310 | ␉␉␊ |
311 | ␉␉␊ |
312 | ␉␉␊ |
313 | ␉␉/*␉␉int i;␊ |
314 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
315 | ␉␉{␊ |
316 | ␉␉␉printf("Parsing kext %d\n", i);␊ |
317 | ␉␉}␊ |
318 | ␉␉*/␊ |
319 | ␉␉␊ |
320 | ␊ |
321 | ␉}␊ |
322 | ␊ |
323 | ␉␊ |
324 | ␉DBG("Loading %s, length %d, version 0x%x\n", filespec, length, version);␊ |
325 | ␉//getc();␊ |
326 | }␊ |
327 | ␊ |
328 | // FIXME: only handles mkext2 entries␊ |
329 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
330 | {␊ |
331 | ␉char* bundleID;␊ |
332 | ␉␊ |
333 | ␉if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return false;␉// Kext is a plist only kext, don't patch␊ |
334 | ␉␊ |
335 | ␉bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));␊ |
336 | ␉␊ |
337 | ␉␊ |
338 | ␉if(patch_gma_deviceid &&␊ |
339 | ␉ (␊ |
340 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||␊ |
341 | ␉␉␉(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)␊ |
342 | ␉␉ )␊ |
343 | ␉ )␊ |
344 | ␉{␊ |
345 | ␉␉return patch_gma_kexts(plist, plistbuffer, start);␊ |
346 | ␉}␊ |
347 | ␉else if(patch_bcm_deviceid && (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0))␊ |
348 | ␉{␊ |
349 | ␉␉return patch_bcm_kext(plist, plistbuffer, start);␊ |
350 | ␊ |
351 | ␉}␊ |
352 | ␉else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDA") == 0)␊ |
353 | ␉{␊ |
354 | ␉␉return patch_hda_kext(plist, plistbuffer, start);␊ |
355 | ␊ |
356 | ␉}␊ |
357 | ␉/*␊ |
358 | ␉else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDAController") == 0)␊ |
359 | ␉{␊ |
360 | ␉␉return patch_hda_controller(plist, plistbuffer, start);␊ |
361 | ␊ |
362 | ␉}␊ |
363 | ␉*/␊ |
364 | ␉return false;␊ |
365 | }␊ |
366 | ␊ |
367 | void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
368 | {␊ |
369 | ␉pci_dt_t* current = arg1;␊ |
370 | ␉if(current)␊ |
371 | ␉{␊ |
372 | ␉␉if(current->class_id == PCI_CLASS_DISPLAY_VGA)␊ |
373 | ␉␉{␊ |
374 | ␉␉␉if(current->vendor_id == 0x8086 && current->device_id == 0x27AE)␊ |
375 | ␉␉␉{␊ |
376 | ␉␉␉␉// TODO: patche based on dev id.␊ |
377 | ␉␉␉␉patch_gma_deviceid = current->device_id;␊ |
378 | ␉␉␉}␊ |
379 | ␉␉}␊ |
380 | ␉␉else if(current->class_id == PCI_CLASS_NETWORK_OTHER) ␊ |
381 | ␉␉{␊ |
382 | ␉␉␉// Patch BCM43xx␊ |
383 | ␉␉␉if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300))␊ |
384 | ␉␉␉{␊ |
385 | ␉␉␉␉patch_bcm_deviceid = current->device_id;␊ |
386 | ␉␉␉}␊ |
387 | ␉␉}␊ |
388 | ␉}␊ |
389 | }␊ |
390 | ␊ |
391 | ␊ |
392 | bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start)␊ |
393 | {␊ |
394 | ␉return false;␊ |
395 | ␉// change the PCI class code to match to. Note: A LegacyHDA plist should do this on it's own␊ |
396 | ␉// As such, it's disabled␊ |
397 | ␊ |
398 | ␉// TODO: read class code␊ |
399 | ␉TagPtr personality;␊ |
400 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
401 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"BuiltInHDA");␉␊ |
402 | ␉TagPtr match_class =XMLCastArray(XMLGetProperty(personality, (const char*)"IOPCIClassMatch"));␊ |
403 | ␉␊ |
404 | ␉␊ |
405 | ␉char* new_str = malloc(strlen("0xXXXX000&0xFFFE0000")+1);␊ |
406 | ␉sprintf(new_str, "0x04030000&0xFFFE0000"); // todo, pass in actual class id␊ |
407 | ␉␊ |
408 | ␉␊ |
409 | ␉char* orig_string = "0x04020000&0xFFFE0000"; //XMLCastString(match_class);␊ |
410 | ␉␊ |
411 | ␉DBG("Attemting to replace '%s' with '%s'\n", orig_string, new_str);␊ |
412 | ␉␊ |
413 | ␉// TODO: verify string doesn't exist first.␊ |
414 | ␉␊ |
415 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(match_class), 1024);␊ |
416 | ␉␊ |
417 | ␉return true;␊ |
418 | ␉␊ |
419 | }␊ |
420 | ␊ |
421 | ␊ |
422 | bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
423 | {␊ |
424 | ␉uint16_t find_codec = 0;␊ |
425 | ␉int full_size, compressed_size, executable_offset;␊ |
426 | ␉void* compressed_data;␊ |
427 | ␉mkext2_file_entry* kext;␊ |
428 | ␉int zlib_result;␊ |
429 | ␉z_stream zstream;␊ |
430 | ␉bool zstream_inited = false;␊ |
431 | ␊ |
432 | ␉switch(0xFF00 & patch_hda_codec)␊ |
433 | ␉{␊ |
434 | ␉␉case 0x0200:␊ |
435 | ␉␉␉find_codec = 0x0262;␊ |
436 | ␉␉␉break;␊ |
437 | ␊ |
438 | ␉␉case 0x0800:␊ |
439 | ␉␉␉find_codec = 0x0885;␊ |
440 | ␉␉␉break;␊ |
441 | ␉␉␉␊ |
442 | ␉␉case 0x0600:␉// specificaly the 662␊ |
443 | ␉␉␉find_codec = 0x0885;␊ |
444 | ␉␉␉break;␊ |
445 | ␉}␊ |
446 | ␉␊ |
447 | ␉if(!find_codec) return false;␉// notify caller that we aren't patching the kext␊ |
448 | ␊ |
449 | ␉␉␊ |
450 | ␉executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
451 | ␉kext = (void*)((char*)start + executable_offset);␊ |
452 | ␊ |
453 | ␉full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
454 | ␉compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
455 | ␉compressed_data = MKEXT2_GET_ENTRY_DATA(kext);␉␊ |
456 | ␉executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
457 | ␉␊ |
458 | ␉␊ |
459 | ␉char* executable = malloc(full_size);␊ |
460 | ␉␊ |
461 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
462 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
463 | ␉zstream.avail_in = compressed_size;␊ |
464 | ␉␊ |
465 | ␉zstream.next_out = (UInt8*)executable;␊ |
466 | ␉zstream.avail_out = full_size;␊ |
467 | ␉␊ |
468 | ␉zstream.zalloc = z_alloc;␊ |
469 | ␉zstream.zfree = z_free;␊ |
470 | ␉␊ |
471 | ␉zlib_result = inflateInit(&zstream);␊ |
472 | ␉if (Z_OK != zlib_result)␊ |
473 | ␉{␊ |
474 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
475 | ␉␉getc();␊ |
476 | ␉}␊ |
477 | ␉else ␊ |
478 | ␉{␊ |
479 | ␉␉zstream_inited = true;␊ |
480 | ␉}␊ |
481 | ␉␊ |
482 | ␉␊ |
483 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
484 | ␉␊ |
485 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
486 | ␉␉␊ |
487 | ␉replace_word(0x10EC | (find_codec << 8), 0xE10EC | (patch_hda_codec << 8), executable, zstream.total_out);␊ |
488 | ␉␊ |
489 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
490 | ␉␊ |
491 | ␉␊ |
492 | ␉zstream.next_in = (UInt8*)executable;␊ |
493 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
494 | ␉␊ |
495 | ␉zstream.avail_in = full_size;␊ |
496 | ␉zstream.avail_out = compressed_size;␊ |
497 | ␉zstream.zalloc = Z_NULL;␊ |
498 | ␉zstream.zfree = Z_NULL;␊ |
499 | ␉zstream.opaque = Z_NULL;␊ |
500 | ␉␊ |
501 | ␉␊ |
502 | ␉␊ |
503 | ␉// Recompress the eecutable␊ |
504 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
505 | ␉if (Z_OK != zlib_result) {␊ |
506 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
507 | ␉␉getc();␊ |
508 | ␉}␊ |
509 | ␉else ␊ |
510 | ␉{␊ |
511 | ␉␉zstream_inited = true;␊ |
512 | ␉}␊ |
513 | ␉␊ |
514 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
515 | ␉␊ |
516 | ␉if (zlib_result == Z_STREAM_END)␊ |
517 | ␉{␊ |
518 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
519 | ␉} ␊ |
520 | ␉else if (zlib_result == Z_OK)␊ |
521 | ␉{␊ |
522 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
523 | ␉␉ */␊ |
524 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
525 | ␉␉␊ |
526 | ␉} ␊ |
527 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
528 | ␉{␊ |
529 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
530 | ␉␉getc();␊ |
531 | ␉}␊ |
532 | ␉␊ |
533 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
534 | ␉␊ |
535 | ␉free(executable);␊ |
536 | ␉␊ |
537 | ␉return true;␉␊ |
538 | ␊ |
539 | }␊ |
540 | ␊ |
541 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
542 | {␊ |
543 | ␉TagPtr personality;␊ |
544 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
545 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"Broadcom 802.11 PCI");␉␊ |
546 | ␉TagPtr match_names =XMLCastArray(XMLGetProperty(personality, (const char*)"IONameMatch"));␊ |
547 | ␊ |
548 | ␉␊ |
549 | ␉char* new_str = malloc(strlen("pci14e4,xxxx")+1);␊ |
550 | ␉sprintf(new_str, "pci14e4,%02x", patch_bcm_deviceid);␊ |
551 | ␊ |
552 | ␉// Check to see if we *really* need to modify the plist, if not, return false␊ |
553 | ␉// so that *if* this were going ot be the only modified kext, the repacking code␊ |
554 | ␉// won't need to be executed.␊ |
555 | ␉int count = XMLTagCount(match_names);␊ |
556 | ␉while(count)␊ |
557 | ␉{␊ |
558 | ␉␉count--;␊ |
559 | ␉␉TagPtr replace =␉XMLGetElement(match_names, count);␉// Modify the second entry␊ |
560 | ␉␉char* orig_string = XMLCastString(replace);␊ |
561 | ␉␉if(strcmp(orig_string, new_str) == 0) return false;␊ |
562 | ␉}␊ |
563 | ␊ |
564 | ␉␊ |
565 | ␉TagPtr replace =␉XMLGetElement(match_names, 1);␉// Modify the second entry␊ |
566 | ␉char* orig_string = XMLCastString(replace);␊ |
567 | ␉␊ |
568 | ␉DBG("Attemting to replace '%s' with '%s'\n", orig_string, new_str);␊ |
569 | ␊ |
570 | ␉// TODO: verify string doesn't exist first.␊ |
571 | ␉␊ |
572 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(replace), 1024);␊ |
573 | ␉␊ |
574 | ␉return true;␊ |
575 | }␊ |
576 | ␊ |
577 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start)␊ |
578 | {␊ |
579 | ␉int exeutable_offset, full_size, compressed_size;␊ |
580 | ␉TagPtr personality;␊ |
581 | ␉long offset;␊ |
582 | ␉int zlib_result;␊ |
583 | ␉z_stream zstream;␊ |
584 | ␉bool zstream_inited = false;␊ |
585 | ␉mkext2_file_entry* kext;␊ |
586 | ␉void* compressed_data;␊ |
587 | ␊ |
588 | ␉exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
589 | ␉kext = (void*)((char*)start + exeutable_offset);␊ |
590 | ␊ |
591 | ␉full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
592 | ␉compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
593 | ␉compressed_data = MKEXT2_GET_ENTRY_DATA(kext);␊ |
594 | ␉␊ |
595 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
596 | ␉if(XMLGetProperty(personality, (const char*)"Intel915"))␊ |
597 | ␉{␊ |
598 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"Intel915");␊ |
599 | ␉}␊ |
600 | ␉else␊ |
601 | ␉{␊ |
602 | ␉␉personality =␉␉XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer");␉␊ |
603 | ␉}␊ |
604 | #if DEBUG_KEXT_PATCHER␊ |
605 | ␉char* pcimatch =␉XMLCastString(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
606 | #endif␊ |
607 | ␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␊ |
608 | ␉␊ |
609 | ␉replace_string("0x27A28086", "0x27AE8086", plistbuffer + offset, 1024);␊ |
610 | ␉␊ |
611 | ␉DBG("Located kext %s\n", bundleID);␊ |
612 | ␉DBG("PCI Match offset = %d, string = %s\n", offset, pcimatch);␊ |
613 | ␉char* executable = malloc(full_size);␊ |
614 | ␉␊ |
615 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
616 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
617 | ␉zstream.avail_in = compressed_size;␊ |
618 | ␉␊ |
619 | ␉zstream.next_out = (UInt8*)executable;␊ |
620 | ␉zstream.avail_out = full_size;␊ |
621 | ␉␊ |
622 | ␉zstream.zalloc = z_alloc;␊ |
623 | ␉zstream.zfree = z_free;␊ |
624 | ␉␊ |
625 | ␉zlib_result = inflateInit(&zstream);␊ |
626 | ␉if (Z_OK != zlib_result)␊ |
627 | ␉{␊ |
628 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
629 | ␉␉getc();␊ |
630 | ␉}␊ |
631 | ␉else ␊ |
632 | ␉{␊ |
633 | ␉␉zstream_inited = true;␊ |
634 | ␉}␊ |
635 | ␉␊ |
636 | ␉␊ |
637 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
638 | ␉␊ |
639 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
640 | ␉␊ |
641 | ␉replace_word(0x27A28086, 0x27AE8086, executable, zstream.total_out);␊ |
642 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
643 | ␉␊ |
644 | ␉␊ |
645 | ␉zstream.next_in = (UInt8*)executable;␊ |
646 | ␉//␉␉zstream.next_out = (UInt8*)((int)compressed_data<<1);␊ |
647 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
648 | ␉␊ |
649 | ␉zstream.avail_in = full_size;␊ |
650 | ␉zstream.avail_out = compressed_size;␊ |
651 | ␉zstream.zalloc = Z_NULL;␊ |
652 | ␉zstream.zfree = Z_NULL;␊ |
653 | ␉zstream.opaque = Z_NULL;␊ |
654 | ␉␊ |
655 | ␉␊ |
656 | ␉␊ |
657 | ␉// Recompress the eecutable␊ |
658 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
659 | ␉if (Z_OK != zlib_result) {␊ |
660 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
661 | ␉␉getc();␊ |
662 | ␉}␊ |
663 | ␉else ␊ |
664 | ␉{␊ |
665 | ␉␉zstream_inited = true;␊ |
666 | ␉}␊ |
667 | ␉␊ |
668 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
669 | ␉␊ |
670 | ␉if (zlib_result == Z_STREAM_END)␊ |
671 | ␉{␊ |
672 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
673 | ␉} ␊ |
674 | ␉else if (zlib_result == Z_OK)␊ |
675 | ␉{␊ |
676 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
677 | ␉␉ */␊ |
678 | ␉␉DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
679 | ␉␉␊ |
680 | ␉} ␊ |
681 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
682 | ␉{␊ |
683 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
684 | ␉␉getc();␊ |
685 | ␉}␊ |
686 | ␉␊ |
687 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
688 | ␉␊ |
689 | ␉free(executable);␊ |
690 | ␉␊ |
691 | ␉return true;␉␊ |
692 | } |