Root/
Source at commit 1079 created 13 years 1 month ago. By meklort, began implimenting Bios disk changes. Code taken from biosfn.c | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␉␊ |
4 | *␉KextPather␊ |
5 | *␉The main purpose of this moduleis to replace the need for programs such as ␊ |
6 | * NetbookInstaller's kext patching routines. This way, Apple's kexts can be␊ |
7 | * patched whe loaded instead. (eg: GMA950 kext, Bluetooth + Wifi kexts)␊ |
8 | */␊ |
9 | #ifndef DEBUG_KEXT_PATCHER␊ |
10 | #define DEBUG_KEXT_PATCHER 0␊ |
11 | #endif␊ |
12 | ␊ |
13 | #if DEBUG_KEXT_PATCHER␊ |
14 | #define DBG(x...)␉printf(x)␊ |
15 | #else␊ |
16 | #define DBG(x...)␊ |
17 | #endif␊ |
18 | ␊ |
19 | ␊ |
20 | #include "libsaio.h"␊ |
21 | #include "zlib.h"␊ |
22 | #include "kext_patcher.h"␊ |
23 | #include "boot.h"␊ |
24 | #include "bootstruct.h"␊ |
25 | #include "pci.h"␊ |
26 | #include "drivers.h"␊ |
27 | #include "mkext.h"␊ |
28 | #include "modules.h"␊ |
29 | #include "hex_editor.h"␊ |
30 | ␊ |
31 | ␊ |
32 | uint16_t patch_gma_deviceid = 0;␊ |
33 | uint16_t patch_bcm_deviceid = 0;␊ |
34 | uint16_t patch_atheros_deviceid = 0;␊ |
35 | uint16_t patch_hda_codec = 0x00;␉␉// TODO; detect proper codec␊ |
36 | ␊ |
37 | ␊ |
38 | /*␊ |
39 | * Space allocation and freeing routines for use by zlib routines.␊ |
40 | */␊ |
41 | void *␊ |
42 | z_alloc(void * notused __unused, u_int num_items, u_int size)␊ |
43 | {␊ |
44 | void * result = NULL;␊ |
45 | z_mem * zmem = NULL;␊ |
46 | uint32_t total = num_items * size;␊ |
47 | uint32_t allocSize = total + sizeof(zmem);␊ |
48 | ␊ |
49 | zmem = (z_mem *)malloc(allocSize);␊ |
50 | if (!zmem) {␊ |
51 | goto finish;␊ |
52 | }␊ |
53 | zmem->alloc_size = allocSize;␊ |
54 | result = (void *)&(zmem->data);␊ |
55 | finish:␊ |
56 | return result;␊ |
57 | }␊ |
58 | ␊ |
59 | void␊ |
60 | z_free(void * notused __unused, void * ptr)␊ |
61 | {␊ |
62 | uint32_t * skipper = (uint32_t *)ptr - 1;␊ |
63 | z_mem * zmem = (z_mem *)skipper;␊ |
64 | free((void *)zmem);␊ |
65 | return;␊ |
66 | }␊ |
67 | ␊ |
68 | ␊ |
69 | ␊ |
70 | ␊ |
71 | /**␊ |
72 | ** KextPatcher_start -> module start␊ |
73 | **␉␉Notified the module system that this module will hook into the ␊ |
74 | **␉␉LoadMatchedModules and LoadDriverMKext functions␊ |
75 | **/␊ |
76 | void KextPatcher_start()␊ |
77 | {␉␉␊ |
78 | ␉// Hooks into the following:␊ |
79 | ␉//␉execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL);␊ |
80 | ␉// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);␊ |
81 | ␊ |
82 | ␉register_hook_callback("PCIDevice", &KextPatcher_hook);␊ |
83 | ␉//register_hook_callback("LoadMatchedModules", &kext_loaded); ␊ |
84 | ␉register_hook_callback("LoadDriverMKext", &mkext_loaded); ␊ |
85 | ␊ |
86 | }␊ |
87 | ␊ |
88 | ␊ |
89 | /**␊ |
90 | ** kext_loaded -> Called whenever a kext is read into memory␊ |
91 | **␉␉This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)␊ |
92 | **␉␉and their plists when they are loaded into memmory␊ |
93 | **/␊ |
94 | void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3)␊ |
95 | {␊ |
96 | ␉//ModulePtr module = moduletmp;␊ |
97 | ␉//long length = *(long*)lengthprt;␊ |
98 | ␉//long length2 = strlen(module->plistAddr);␊ |
99 | ␉// *(long*)lengthprt = length2 + 5 * 1024 * 1024;␊ |
100 | ␊ |
101 | ␉//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);␊ |
102 | ␉//getc();␊ |
103 | }␊ |
104 | ␊ |
105 | ␊ |
106 | /**␊ |
107 | ** mkext_loaded -> Called whenever an mkext is in read into memory␊ |
108 | **␉␉This function will be used to patch mkext. Matching kexts will be␊ |
109 | **␉␉Extracted, modified, and then compressed again. Note: I need to determine␊ |
110 | **␉␉what sort of slowdown this will cause and if it's worth implimenting.␊ |
111 | **/␊ |
112 | void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3)␊ |
113 | {␊ |
114 | ␉const char* hda_codec␉␉= 0;␊ |
115 | ␉int len␉␉␉␉␉␉= 0;␊ |
116 | ␉mkext_basic_header* package = packagetmp;␊ |
117 | ␉int version␉␉␉␉␉= MKEXT_GET_VERSION(package);␊ |
118 | ␊ |
119 | ␉if (getValueForKey(kHDACodec, &hda_codec, &len, &bootInfo->bootConfig))␊ |
120 | ␉{␊ |
121 | ␉␉patch_hda_codec = 0;␊ |
122 | ␉␉int index = 0;␊ |
123 | ␉␉while(len--)␊ |
124 | ␉␉{␊ |
125 | ␉␉␉patch_hda_codec <<= 4;␊ |
126 | ␉␉␉patch_hda_codec |= chartohex(hda_codec[index]);␊ |
127 | ␉␉␉index++;␊ |
128 | ␉␉}␊ |
129 | ␉}␊ |
130 | ␉␉␊ |
131 | ␉if(!NEEDS_PATCHING) return;␉// No need to apply a patch, hardware doesn't need it␊ |
132 | ␉␊ |
133 | ␊ |
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 | ␉␉ Adler32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )␊ |
141 | {␊ |
142 | return; // Don't try to patch a bad mkext␊ |
143 | }␉␊ |
144 | ␉␉␊ |
145 | ␉␊ |
146 | ␉if(version == 0x01008000) // mkext1␊ |
147 | ␉{␊ |
148 | ␉␉// mkext1 uses lzss␊ |
149 | ␉␉mkext1_header* package = packagetmp;␊ |
150 | ␉␉int i;␊ |
151 | ␉␉for(i = 0; i < MKEXT_GET_COUNT(package); i++)␊ |
152 | ␉␉{␊ |
153 | ␉␉␉DBG("Parsing kext %d\n", i);␊ |
154 | ␉␉␉//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);␊ |
155 | ␉␉␉// uses decompress_lzss␊ |
156 | ␉␉␉// TODO: handle kext␊ |
157 | ␉␉}␊ |
158 | ␉}␊ |
159 | ␉else if((version & 0xFFFF0000) == 0x02000000) // mkext2␊ |
160 | ␉{␊ |
161 | ␉␉DBG("Mkext2 package located at 0x%X\n", package);␊ |
162 | ␊ |
163 | ␉␉// mkext2 uses zlib␉␉␊ |
164 | ␉␉mkext2_header*␉package = packagetmp;␊ |
165 | ␉␉z_stream␉␉zstream;␊ |
166 | ␉␉bool␉␉␉zstream_inited = false;␊ |
167 | ␉␉int␉␉␉␉zlib_result;␊ |
168 | ␉␉int␉␉␉␉plist_offset = MKEXT2_GET_PLIST(package);␊ |
169 | ␉␉␊ |
170 | ␉␉char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));␊ |
171 | ␉␉␊ |
172 | ␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
173 | ␉␉zstream.next_in = (UInt8*)((char*)package + plist_offset);␊ |
174 | ␉␉zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
175 | ␉␉␊ |
176 | ␉␉zstream.next_out = (UInt8*)plist;␊ |
177 | ␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
178 | ␉␉␊ |
179 | ␉␉zstream.zalloc = z_alloc;␊ |
180 | ␉␉zstream.zfree = z_free;␊ |
181 | ␉␉␉␉␊ |
182 | ␉␉zlib_result = inflateInit(&zstream);␊ |
183 | ␉␉if (Z_OK != zlib_result)␊ |
184 | ␉␉{␊ |
185 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
186 | ␉␉␉getc();␊ |
187 | ␉␉}␊ |
188 | ␉␉else ␊ |
189 | ␉␉{␊ |
190 | ␉␉␉zstream_inited = true;␊ |
191 | ␉␉}␊ |
192 | ␊ |
193 | ␉␉␊ |
194 | ␉␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
195 | ␉␉if (zstream_inited) inflateEnd(&zstream);␊ |
196 | ␊ |
197 | ␉␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);␊ |
198 | ␉␉if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)␊ |
199 | ␉␉{␉␉␉␊ |
200 | ␉␉␉TagPtr plistData;␊ |
201 | ␉␉␉TagPtr allDicts;␊ |
202 | ␉␉␉bzero(&plistData, sizeof(plistData));␊ |
203 | ␉␉␉bzero(&allDicts, sizeof(allDicts));␊ |
204 | ␉␉␉␊ |
205 | ␉␉␉XMLParseFile( plist, &plistData );␊ |
206 | ␊ |
207 | ␉␉␉int count;␊ |
208 | ␊ |
209 | ␉␉␉allDicts = XMLGetProperty(plistData, kMKEXTInfoDictionariesKey);␊ |
210 | ␉␉␉␊ |
211 | ␉␉␉bool patched = false;␊ |
212 | ␉␉␉for(count = XMLTagCount(allDicts);␊ |
213 | ␉␉␉␉count > 0;␊ |
214 | ␉␉␉␉count--)␊ |
215 | ␉␉␉{␊ |
216 | ␉␉␉␉TagPtr kextEntry = XMLGetElement(allDicts, count);␊ |
217 | ␉␉␉␉patched |= patch_kext(kextEntry, plist, package);␊ |
218 | ␉␉␉}␊ |
219 | ␉␉␉␊ |
220 | ␊ |
221 | ␉␉␉if(patched)␊ |
222 | ␉␉␉{␊ |
223 | ␉␉␉␉zstream_inited = false;␊ |
224 | ␉␉␉␉// Recompress the plist␊ |
225 | ␉␉␉␉bzero(&zstream, sizeof(zstream));␉␉␊ |
226 | ␉␉␉␉zstream.next_in = (UInt8*)plist;␊ |
227 | ␉␉␉␉zstream.next_out = (UInt8*)package + plist_offset;␊ |
228 | ␉␉␉␉zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package);␊ |
229 | ␉␉␉␉zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2;␉// Give us some extra free space, just in case␊ |
230 | ␉␉␉␉zstream.zalloc = Z_NULL;␊ |
231 | ␉␉␉␉zstream.zfree = Z_NULL;␊ |
232 | ␉␉␉␉zstream.opaque = Z_NULL;␊ |
233 | ␉␉␉␉␊ |
234 | ␉␉␉␉␊ |
235 | ␉␉␉␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
236 | ␉␉␉␉if (Z_OK != zlib_result) {␊ |
237 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
238 | ␉␉␉␉␉getc();␊ |
239 | ␉␉␉␉}␊ |
240 | ␉␉␉␉else ␊ |
241 | ␉␉␉␉{␊ |
242 | ␉␉␉␉␉zstream_inited = true;␊ |
243 | ␉␉␉␉}␊ |
244 | ␉␉␉␉␊ |
245 | ␉␉␉␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
246 | ␉␉␉␉␊ |
247 | ␉␉␉␉if (zlib_result == Z_STREAM_END)␊ |
248 | ␉␉␉␉{␊ |
249 | ␉␉␉␉␉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));␊ |
250 | ␉␉␉␉} ␊ |
251 | ␉␉␉␉else if (zlib_result == Z_OK)␊ |
252 | ␉␉␉␉{␊ |
253 | ␉␉␉␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
254 | ␉␉␉␉␉ */␊ |
255 | ␉␉␉␉␉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));␊ |
256 | ␉␉␉␉␉␊ |
257 | ␉␉␉␉} ␊ |
258 | ␉␉␉␉else if (zlib_result != Z_STREAM_ERROR)␊ |
259 | ␉␉␉␉{␊ |
260 | ␉␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
261 | ␉␉␉␉␉getc();␊ |
262 | ␉␉␉␉}␊ |
263 | ␉␉␉␉␊ |
264 | ␉␉␉␉if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package))␊ |
265 | ␉␉␉␉{␊ |
266 | ␉␉␉␉␉// Update the mkext length␊ |
267 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out);␊ |
268 | ␉␉␉␉␉MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
269 | ␉␉␉␉␉*((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package);␊ |
270 | ␉␉␉␉␉*((int*)lengthtmp) += zstream.total_out;␊ |
271 | ␉␉␉␉}␊ |
272 | ␉␉␉␉␉␉␉␉␊ |
273 | ␉␉␉␉if (zstream_inited) deflateEnd(&zstream);␊ |
274 | ␉␉␉␉␊ |
275 | ␉␉␉␉␊ |
276 | ␉␉␉␉␊ |
277 | ␉␉␉␉// re adler32 the new mkext2 package␊ |
278 | ␉␉␉␉MKEXT_HDR_CAST(package)->adler32 = MKEXT_SWAP(Adler32((unsigned char *)&package->version,␊ |
279 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉ MKEXT_GET_LENGTH(package) - 0x10));␊ |
280 | ␉␉␉}␊ |
281 | ␉␉}␊ |
282 | ␉␉else␊ |
283 | ␉␉{␊ |
284 | ␉␉␉printf("ZLIB Error: %s\n", zstream.msg);␊ |
285 | ␉␉␉getc();␊ |
286 | ␉␉}␊ |
287 | ␉}␊ |
288 | }␊ |
289 | ␊ |
290 | // FIXME: only handles mkext2 entries␊ |
291 | bool patch_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
292 | {␊ |
293 | ␉char* bundleID;␊ |
294 | ␉␊ |
295 | ␉if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return false;␉// Kext is a plist only kext, don't patch␊ |
296 | ␉␊ |
297 | ␉bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));␊ |
298 | ␉␊ |
299 | ␉␊ |
300 | ␉if(patch_gma_deviceid &&␊ |
301 | ␉ ((strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||␊ |
302 | ␉␉ (strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)))␊ |
303 | ␉{␊ |
304 | ␉␉return patch_gma_kexts(plist, plistbuffer, start);␊ |
305 | ␉}␊ |
306 | ␉else if(patch_bcm_deviceid && (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0))␊ |
307 | ␉{␊ |
308 | ␉␉return patch_bcm_kext(plist, plistbuffer, start);␊ |
309 | ␉}␊ |
310 | ␉else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDA") == 0)␊ |
311 | ␉{␊ |
312 | ␉␉return patch_hda_kext(plist, plistbuffer, start);␊ |
313 | ␉}␊ |
314 | ␉else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDAController") == 0)␊ |
315 | ␉{␊ |
316 | ␉␉return patch_hda_controller(plist, plistbuffer, start);␊ |
317 | ␉}␊ |
318 | ␉else if(patch_atheros_deviceid && strcmp(bundleID, "com.apple.driver.AirPort.Atheros21") == 0)␊ |
319 | ␉{␊ |
320 | ␉␉return patch_atheros_kext(plist, plistbuffer, start);␊ |
321 | ␉}␊ |
322 | ␉␊ |
323 | ␉return false;␊ |
324 | }␊ |
325 | ␊ |
326 | void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
327 | {␊ |
328 | ␉pci_dt_t* current = arg1;␊ |
329 | ␉if(current)␊ |
330 | ␉{␊ |
331 | ␉␉switch(current->class_id)␊ |
332 | ␉␉{␊ |
333 | ␉␉␉case PCI_CLASS_DISPLAY_VGA:␊ |
334 | ␉␉␉␉if(current->vendor_id == 0x8086 && ␊ |
335 | ␉␉␉␉ (␊ |
336 | ␉␉␉␉␉current->device_id == 0x27AE ||␊ |
337 | ␉␉␉␉␉current->device_id == 0xA001 ||␊ |
338 | ␉␉␉␉␉current->device_id == 0xA002 ||␊ |
339 | ␉␉␉␉␉current->device_id == 0xA011 ||␊ |
340 | ␉␉␉␉␉current->device_id == 0xA012␊ |
341 | ␊ |
342 | ␉␉␉␉␉)␊ |
343 | ␉␉␉␉ )␊ |
344 | ␉␉␉␉{␊ |
345 | ␉␉␉␉␉patch_gma_deviceid = current->device_id;␊ |
346 | ␉␉␉␉}␊ |
347 | ␉␉␉␉break;␊ |
348 | ␉␉␉␉␊ |
349 | ␉␉␉case PCI_CLASS_NETWORK_OTHER:␊ |
350 | ␉␉␉␉␊ |
351 | ␉␉␉␉// Patch BCM43xx␊ |
352 | ␉␉␉␉if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFFD0) == 0x4300))␊ |
353 | ␉␉␉␉{␊ |
354 | ␉␉␉␉␉patch_bcm_deviceid = current->device_id;␊ |
355 | ␉␉␉␉}␊ |
356 | ␉␉␉␉else if(current->vendor_id == 0x168C && current->device_id == 0x002B)␊ |
357 | ␉␉␉␉{␊ |
358 | ␉␉␉␉␉patch_atheros_deviceid = current->device_id;␊ |
359 | ␉␉␉␉}␊ |
360 | ␉␉␉␉break;␊ |
361 | ␉␉}␊ |
362 | ␉}␊ |
363 | }␊ |
364 | ␊ |
365 | ␊ |
366 | bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start)␊ |
367 | {␊ |
368 | ␉return false;␊ |
369 | ␉// change the PCI class code to match to. Note: A LegacyHDA plist should do this on it's own␊ |
370 | ␉// As such, it's disabled␊ |
371 | ␊ |
372 | ␉// TODO: read class code␊ |
373 | ␉TagPtr personality;␊ |
374 | ␉personality =␉␉XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
375 | ␉personality =␉␉XMLGetProperty(personality, (const char*)"BuiltInHDA");␉␊ |
376 | ␉TagPtr match_class =XMLCastArray(XMLGetProperty(personality, (const char*)"IOPCIClassMatch"));␊ |
377 | ␉␊ |
378 | ␉␊ |
379 | ␉char* new_str = malloc(sizeof("0xXXXX000&0xFFFE0000"));␊ |
380 | ␉sprintf(new_str, "0x04030000&0xFFFE0000"); // todo, pass in actual class id␊ |
381 | ␉␊ |
382 | ␉␊ |
383 | ␉char* orig_string = "0x04020000&0xFFFE0000"; //XMLCastString(match_class);␊ |
384 | ␉␊ |
385 | ␉printf("Attemting to replace '%s' with '%s'\n", orig_string, new_str);␊ |
386 | ␉␊ |
387 | ␉// TODO: verify string doesn't exist first.␊ |
388 | ␉␊ |
389 | ␉replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(match_class), 1024);␊ |
390 | ␉␊ |
391 | ␉return true;␊ |
392 | ␉␊ |
393 | }␊ |
394 | ␊ |
395 | ␊ |
396 | bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
397 | {␊ |
398 | ␉uint16_t find_codec␉= 0;␊ |
399 | ␉int full_size, compressed_size, executable_offset;␊ |
400 | ␉void* compressed_data;␊ |
401 | ␉mkext2_file_entry* kext;␊ |
402 | ␉int zlib_result;␊ |
403 | ␉z_stream zstream;␊ |
404 | ␉bool zstream_inited = false;␊ |
405 | ␊ |
406 | ␉switch(patch_hda_codec & 0xFF00)␊ |
407 | ␉{␊ |
408 | ␉␉case 0x0200:␊ |
409 | ␉␉␉find_codec = 0x0262;␊ |
410 | ␉␉␉break;␊ |
411 | ␊ |
412 | ␉␉case 0x0800:␊ |
413 | ␉␉␉find_codec = 0x0885;␊ |
414 | ␉␉␉break;␊ |
415 | ␉␉␉␊ |
416 | ␉␉case 0x0600:␉// specificaly the 662␊ |
417 | ␉␉␉find_codec = 0x0885;␊ |
418 | ␉␉␉break;␊ |
419 | ␉}␊ |
420 | ␉if(!find_codec) return false;␉// notify caller that we aren't patching the kext␊ |
421 | ␉␉␊ |
422 | ␉executable_offset␉= XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
423 | ␉kext␉␉␉␉= (void*)((char*)start + executable_offset);␊ |
424 | ␉full_size␉␉␉= MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
425 | ␉compressed_size␉␉= MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
426 | ␉compressed_data␉␉= MKEXT2_GET_ENTRY_DATA(kext);␉␊ |
427 | ␉executable_offset␉= XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
428 | ␉␊ |
429 | ␉␊ |
430 | ␉char* executable = malloc(full_size);␊ |
431 | ␉␊ |
432 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
433 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
434 | ␉zstream.avail_in = compressed_size;␊ |
435 | ␉␊ |
436 | ␉zstream.next_out = (UInt8*)executable;␊ |
437 | ␉zstream.avail_out = full_size;␊ |
438 | ␉␊ |
439 | ␉zstream.zalloc = z_alloc;␊ |
440 | ␉zstream.zfree = z_free;␊ |
441 | ␉␊ |
442 | ␉zlib_result = inflateInit(&zstream);␊ |
443 | ␉if (Z_OK != zlib_result)␊ |
444 | ␉{␊ |
445 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
446 | ␉␉getc();␊ |
447 | ␉}␊ |
448 | ␉else ␊ |
449 | ␉{␊ |
450 | ␉␉zstream_inited = true;␊ |
451 | ␉}␊ |
452 | ␉␊ |
453 | ␉␊ |
454 | ␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
455 | ␉␊ |
456 | ␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
457 | ␉␉␊ |
458 | ␉/*int times = */replace_word(0x10EC0000 | (find_codec), 0x10EC0000 | (patch_hda_codec), executable, zstream.total_out);␊ |
459 | ␉if (zstream_inited) inflateEnd(&zstream);␊ |
460 | ␉␊ |
461 | ␉␊ |
462 | ␉zstream.next_in = (UInt8*)executable;␊ |
463 | ␉zstream.next_out = (UInt8*)compressed_data;␊ |
464 | ␉␊ |
465 | ␉zstream.avail_in = full_size;␊ |
466 | ␉zstream.avail_out = compressed_size<<1;␊ |
467 | ␉zstream.zalloc = Z_NULL;␊ |
468 | ␉zstream.zfree = Z_NULL;␊ |
469 | ␉zstream.opaque = Z_NULL;␊ |
470 | ␉␊ |
471 | ␉␊ |
472 | ␉␊ |
473 | ␉// Recompress the eecutable␊ |
474 | ␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
475 | ␉if (Z_OK != zlib_result) {␊ |
476 | ␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
477 | ␉␉getc();␊ |
478 | ␉}␊ |
479 | ␉else ␊ |
480 | ␉{␊ |
481 | ␉␉zstream_inited = true;␊ |
482 | ␉}␊ |
483 | ␉␊ |
484 | ␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
485 | ␉␊ |
486 | ␉if (zlib_result == Z_STREAM_END)␊ |
487 | ␉{␊ |
488 | ␉␉DBG("Deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size);␊ |
489 | ␉} ␊ |
490 | ␉else if (zlib_result == Z_OK)␊ |
491 | ␉{␊ |
492 | ␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
493 | ␉␉ */␊ |
494 | ␉␉DBG("Buffer FULL: deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size);␊ |
495 | ␉␉printf("Unable to patch AppleHDA\n");␊ |
496 | ␉␉␊ |
497 | ␉} ␊ |
498 | ␉else if (zlib_result != Z_STREAM_ERROR)␊ |
499 | ␉{␊ |
500 | ␉␉printf("AppleHDA: ZLIB Deflate Error: %s\n", zstream.msg);␊ |
501 | ␉␉getc();␊ |
502 | ␉}␊ |
503 | ␉␊ |
504 | ␉if (zstream_inited) deflateEnd(&zstream);␊ |
505 | ␉␊ |
506 | ␉if(zstream.total_out < compressed_size) kext->compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
507 | ␊ |
508 | ␉␊ |
509 | ␉free(executable);␊ |
510 | ␉␊ |
511 | ␉return true;␉␊ |
512 | ␊ |
513 | }␊ |
514 | ␊ |
515 | ␊ |
516 | /** Patches an array element within a personality. NOTE: string sizes should match **/␊ |
517 | bool patch_plist_entry(TagPtr plist, char* plistbuffer, const char* personalityName, const char* propertyName, const char* nameMatch)␊ |
518 | {␊ |
519 | ␉TagPtr personality␉= XMLGetProperty(XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities)), personalityName);␉␊ |
520 | ␉TagPtr match_names␉= XMLCastArray(XMLGetProperty(personality, propertyName));␊ |
521 | ␉TagPtr replace␉␉= XMLGetElement(match_names, 0);␉// Modify the first entry␊ |
522 | ␉int count␉␉␉= XMLTagCount(match_names);␊ |
523 | ␉␊ |
524 | ␉while(count)␊ |
525 | ␉{␊ |
526 | ␉␉char* orig_string␉= XMLCastString(XMLGetElement(match_names, --count));␊ |
527 | ␉␉if(strcmp(orig_string, nameMatch) == 0) return false;␉␉␉// Entry already exists, no need tmo modify plist + recompress␊ |
528 | ␉}␊ |
529 | ␊ |
530 | ␉char* orig_string␉= XMLCastString(replace);␊ |
531 | ␉verbose("Patching %s, replacing %s with %s\n", personalityName, orig_string, nameMatch);␊ |
532 | ␉replace_string(orig_string, nameMatch, plistbuffer + XMLCastStringOffset(replace), 10240);␊ |
533 | ␉return true;␊ |
534 | }␊ |
535 | ␊ |
536 | bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
537 | {␊ |
538 | ␉char* new_str␉␉= malloc(sizeof("pci14e4,xxxx"));␉␊ |
539 | ␉sprintf(new_str, "pci14e4,%02x", patch_bcm_deviceid);␊ |
540 | ␉return patch_plist_entry(plist, plistbuffer, "Broadcom 802.11 PCI", "IONameMatch", new_str);␊ |
541 | }␊ |
542 | ␊ |
543 | bool patch_atheros_kext(TagPtr plist, char* plistbuffer, void* start)␊ |
544 | {␊ |
545 | ␉char* new_str␉␉= malloc(sizeof("pci14e4,xxxx"));␉␊ |
546 | ␉sprintf(new_str, "pci168c,%02x", patch_atheros_deviceid);␊ |
547 | ␉return patch_plist_entry(plist, plistbuffer, "Atheros Wireless LAN PCI", "IONameMatch", new_str);␊ |
548 | }␊ |
549 | ␊ |
550 | bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start)␊ |
551 | {␊ |
552 | ␉TagPtr personality␉␉␉= XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));␊ |
553 | ␉int exeutable_offset␉␉= XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));␊ |
554 | ␉mkext2_file_entry* kext␉␉= (void*)((char*)start + exeutable_offset);␊ |
555 | ␉int full_size␉␉␉␉= MKEXT2_GET_ENTRY_FULLSIZE(kext);␊ |
556 | ␉int compressed_size␉␉␉= MKEXT2_GET_ENTRY_COMPSIZE(kext);␊ |
557 | ␉void* compressed_data␉␉= MKEXT2_GET_ENTRY_DATA(kext);␊ |
558 | ␉char* executable␉␉␉= malloc(full_size);␊ |
559 | ␉int zlib_result␉␉␉␉= Z_OK;␊ |
560 | ␉long offset;␊ |
561 | ␉z_stream zstream;␊ |
562 | ␊ |
563 | ␉bzero(&zstream, sizeof(zstream));␉␉␊ |
564 | ␉zstream.next_in = (UInt8*)compressed_data;␊ |
565 | ␉zstream.avail_in = compressed_size;␊ |
566 | ␉␊ |
567 | ␉zstream.next_out = (UInt8*)executable;␊ |
568 | ␉zstream.avail_out = full_size;␊ |
569 | ␉␊ |
570 | ␉zstream.zalloc = z_alloc;␊ |
571 | ␉zstream.zfree = z_free;␊ |
572 | ␉␊ |
573 | ␉zlib_result = inflateInit(&zstream);␊ |
574 | ␉if (Z_OK != zlib_result)␊ |
575 | ␉{␊ |
576 | ␉␉printf("ZLIB Inflate Error: %s\n", zstream.msg);␊ |
577 | ␉␉getc();␊ |
578 | ␉}␊ |
579 | ␉else ␊ |
580 | ␉{␊ |
581 | ␉␉zlib_result = inflate(&zstream, Z_FINISH);␊ |
582 | ␉␉␊ |
583 | ␉␉DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
584 | ␉␉␊ |
585 | ␉␉char* newstring = malloc(sizeof("0x00008086"));␊ |
586 | ␉␉sprintf(newstring, "0x%04x", 0x8086 | (patch_gma_deviceid << 16));␊ |
587 | ␉␉␊ |
588 | ␉␉␊ |
589 | ␉␉if(XMLGetProperty(personality, (const char*)"Intel915"))␊ |
590 | ␉␉{␊ |
591 | ␉␉␉if((patch_gma_deviceid & 0xFF00) != 0xA000)␉// not GMA3150␊ |
592 | ␉␉␉{␊ |
593 | ␉␉␉␉verbose("Patching AppleIntelGMA950.kext\n");␊ |
594 | ␉␉␉␉personality =␉XMLGetProperty(personality, (const char*)"Intel915"); // IOAccelerator kext␊ |
595 | ␉␉␉␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␉␉␊ |
596 | ␉␉␉␉␊ |
597 | ␉␉␉␉replace_string("0x27A28086", newstring, plistbuffer + offset, 10240);␊ |
598 | ␉␉␉␉replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out);␊ |
599 | ␉␉␉}␊ |
600 | ␉␉}␊ |
601 | ␉␉else if(XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer"))␊ |
602 | ␉␉{␊ |
603 | ␉␉␉verbose("Patching AppleIntelIntegratedFramebuffer\n");␊ |
604 | ␉␉␉personality =␉XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer");␊ |
605 | ␉␉␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␉␉␊ |
606 | ␉␉␉␊ |
607 | ␉␉␉if((patch_gma_deviceid & 0xFF00) == 0xA000)␉// GMA3150␊ |
608 | ␉␉␉{␊ |
609 | ␉␉␉␉// Cursor corruption fix.␊ |
610 | ␉␉␉␉// This patch changes the cursor address from␊ |
611 | ␉␉␉␉// a physical address (used in the gma950) to an offset (used in the gma3150).␊ |
612 | ␉␉␉␉//␉␉␉␉␉{0x8b, 0x55, 0x08, 0x83, 0xba, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x7e, 0x36, 0x89, 0x04, 0x24, 0xe8, 0x6b, 0xbc, 0xff, 0xff};␊ |
613 | ␉␉␉␉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␊ |
614 | ␉␉␉␉char new_bytes[] = {0xb8, 0x00, 0x00, 0x00, 0x02, 0xEB, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};␉// jump past getPhysicalAddress binding. NOTE: last six bytes are unusable, set to 0 for compression␊ |
615 | ␉␉␉␉replace_bytes(find_bytes, sizeof(find_bytes), new_bytes, sizeof(new_bytes), executable, zstream.total_out);␊ |
616 | ␉␉␉}␊ |
617 | ␉␉␉replace_string("0x27A28086", newstring, plistbuffer + offset, 10240);␊ |
618 | ␉␉␉replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out);␊ |
619 | ␉␉␉␊ |
620 | ␉␉}␊ |
621 | ␉␉else if(XMLGetProperty(personality, (const char*)"Intel965"))␊ |
622 | ␉␉{␊ |
623 | ␉␉␉verbose("Patching AppleIntelGMAX3100.kext\n");␊ |
624 | ␉␉␉personality =␉XMLGetProperty(personality, (const char*)"Intel965");␊ |
625 | ␉␉␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␉␉␊ |
626 | ␉␉␉␊ |
627 | ␉␉␉replace_string("0x2a028086", newstring, plistbuffer + offset, 10240);␊ |
628 | ␉␉}␊ |
629 | ␉␉else if(XMLGetProperty(personality, (const char*)"AppleIntelGMAX3100FB"))␊ |
630 | ␉␉{␊ |
631 | ␉␉␉verbose("Patching AppleIntelGMAX3100FB.kext\n");␊ |
632 | ␉␉␉personality =␉XMLGetProperty(personality, (const char*)"AppleIntelGMAX3100FB");␊ |
633 | ␉␉␉␊ |
634 | ␉␉␉offset =␉␉XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));␉␉␊ |
635 | ␉␉␉replace_string("0x2A028086", newstring, plistbuffer + offset, 10240);␊ |
636 | ␉␉␉replace_word(0x2A028086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out);␊ |
637 | ␉␉}␊ |
638 | ␉␉else␊ |
639 | ␉␉{␊ |
640 | ␉␉␉return false;␊ |
641 | ␉␉}␊ |
642 | ␉␉␊ |
643 | ␉␉␊ |
644 | ␉␉inflateEnd(&zstream);␊ |
645 | ␉␉␊ |
646 | ␉␉// Recompress the executable␊ |
647 | ␉␉zstream.next_in = (UInt8*)executable;␊ |
648 | ␉␉zstream.next_out = (UInt8*)compressed_data;␊ |
649 | ␉␉␊ |
650 | ␉␉zstream.avail_in = full_size;␊ |
651 | ␉␉zstream.avail_out = compressed_size;␊ |
652 | ␉␉zstream.zalloc = Z_NULL;␊ |
653 | ␉␉zstream.zfree = Z_NULL;␊ |
654 | ␉␉zstream.opaque = Z_NULL;␊ |
655 | ␉␉␊ |
656 | ␉␉zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);␊ |
657 | ␉␉if (Z_OK != zlib_result) {␊ |
658 | ␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
659 | ␉␉␉getc();␊ |
660 | ␉␉}␊ |
661 | ␉␉else ␊ |
662 | ␉␉{␉␉␊ |
663 | ␉␉␉zlib_result = deflate(&zstream, Z_FINISH);␊ |
664 | ␉␉␉␊ |
665 | ␉␉␉if (zlib_result == Z_STREAM_END)␊ |
666 | ␉␉␉{␊ |
667 | ␉␉␉␉DBG("Deflated result is %d, avail: %d bytes, out: %d bytes, full: %d\n", zlib_result, compressed_size, zstream.total_out, full_size);␊ |
668 | ␉␉␉} ␊ |
669 | ␉␉␉else if (zlib_result == Z_OK)␊ |
670 | ␉␉␉{␊ |
671 | ␉␉␉␉/* deflate filled output buffer, meaning the data doesn't compress.␊ |
672 | ␉␉␉␉ */␊ |
673 | ␉␉␉␉printf("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);␊ |
674 | ␉␉␉␉printf("ERROR: Unable to compress patched kext, not enough room.\n");␊ |
675 | ␉␉␉␉pause();␊ |
676 | ␉␉␉␉␊ |
677 | ␉␉␉} ␊ |
678 | ␉␉␉else if (zlib_result != Z_STREAM_ERROR)␊ |
679 | ␉␉␉{␊ |
680 | ␉␉␉␉printf("ZLIB Deflate Error: %s\n", zstream.msg);␊ |
681 | ␉␉␉␉getc();␊ |
682 | ␉␉␉}␊ |
683 | ␉␉␉if(zstream.total_out < compressed_size) kext->compressed_size = MKEXT_SWAP(zstream.total_out);␊ |
684 | ␉␉␉␊ |
685 | ␉␉␉␊ |
686 | ␉␉␉deflateEnd(&zstream);␊ |
687 | ␉␉}␊ |
688 | ␉}␊ |
689 | ␉␊ |
690 | ␉free(executable);␊ |
691 | ␉␊ |
692 | ␉return true;␉␊ |
693 | }␊ |
694 | ␊ |
695 | int chartohex(char c)␊ |
696 | {␊ |
697 | ␉if(c <= '9' && c >= '0')␉␉return c - '0';␉// c is between 0 and 9␊ |
698 | ␉else if(c <= 'F' && c >= 'A')␉return c - 'A' + 10; // c = 10 - 15;␊ |
699 | ␉else if(c <= 'f' && c >= 'a')␉return c - 'a' + 10; // c = 10 - 15;␊ |
700 | ␊ |
701 | ␉return 0;␊ |
702 | } |