Root/
Source at commit 970 created 13 years 23 days ago. By macman, ati.c, removed duplicate default "ATI Radeon HD 5400 Series", added Gigabyte "AMD Radeon HD 6850" OC device ID and added additional AMD 6000 cards with their default settings. Removed some blank lines. | |
---|---|
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 | } |