Root/
Source at commit 360 created 13 years 11 months ago. By azimutz, End "search algo" related stuff. Check Mac OS X version on processBootOptions() so we can override Boot.plist from OS specific folders. This check doesn't print to screen so, we still check Mac OS X version on boot.c as before. Initializing gMacOSVersion on options.c instead of boot.c. Also "Draw background, turn off any GUI elements and update VRAM" a bit early (as early as possible) on common_boot, so we can catch verbose from loadOverrideConfig. If i didn't forgot something, this concludes the search algo as is atm :) | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2009 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "kernel_patcher.h"␊ |
8 | #include "platform.h"␊ |
9 | ␊ |
10 | extern PlatformInfo_t Platform;␊ |
11 | ␊ |
12 | ␊ |
13 | #define SYMBOL_CPUID_SET_INFO␉␉␉␉0␊ |
14 | #define SYMBOL_PANIC␉␉␉␉␉␉1␊ |
15 | #define SYMBOL_PMCPUEXITHALTTOOFF␉␉␉2␊ |
16 | #define SYMBOL_LAPIC_INIT␉␉␉␉␉3␊ |
17 | #define SYMBOL_COMMPAGE_STUFF_ROUTINE␉␉4␊ |
18 | #define NUM_SYMBOLS␉␉␉␉␉␉␉5␊ |
19 | ␊ |
20 | #define SYMBOL_CPUID_SET_INFO_STRING␉␉"_cpuid_set_info"␊ |
21 | #define SYMBOL_PANIC_STRING␉␉␉␉␉"_panic"␊ |
22 | #define SYMBOL_PMCPUEXITHALTTOOFF_STRING␉"_pmCPUExitHaltToOff"␊ |
23 | #define SYMBOL_LAPIC_INIT_STRING␉␉␉"_lapic_init"␊ |
24 | #define SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING␉"_commpage_stuff_routine"␊ |
25 | ␊ |
26 | char* kernelSymbols[NUM_SYMBOLS] = {␊ |
27 | ␉SYMBOL_CPUID_SET_INFO_STRING,␊ |
28 | ␉SYMBOL_PANIC_STRING,␊ |
29 | ␉SYMBOL_PMCPUEXITHALTTOOFF_STRING,␊ |
30 | ␉SYMBOL_LAPIC_INIT_STRING,␊ |
31 | ␉SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING␊ |
32 | };␊ |
33 | ␊ |
34 | UInt32 kernelSymbolAddresses[NUM_SYMBOLS] = {␊ |
35 | ␉0,␊ |
36 | ␉0,␊ |
37 | ␉0,␊ |
38 | ␉0,␊ |
39 | ␉0␊ |
40 | };␊ |
41 | ␊ |
42 | ␊ |
43 | UInt32 textSection = 0;␊ |
44 | UInt32 textAddress = 0;␊ |
45 | ␊ |
46 | ␊ |
47 | void HelloWorld_start();␊ |
48 | ␊ |
49 | void KernelPatcher_start()␊ |
50 | {␊ |
51 | ␉printf("KernelPatcher(), about to call HelloWorld_start()\n");␊ |
52 | ␉getc();␊ |
53 | ␉HelloWorld_start();␊ |
54 | ␊ |
55 | }␊ |
56 | ␊ |
57 | ␊ |
58 | ␊ |
59 | ␊ |
60 | void patch_kernel(void* kernelData)␊ |
61 | {␊ |
62 | ␉switch (locate_symbols((void*)kernelData)) {␊ |
63 | ␉␉case KERNEL_32:␊ |
64 | ␉␉␉patch_kernel_32((void*)kernelData);␊ |
65 | ␉␉␉break;␊ |
66 | ␉␉␉␊ |
67 | ␉␉case KERNEL_64:␊ |
68 | ␉␉default:␊ |
69 | ␉␉␉patch_kernel_64((void*)kernelData);␊ |
70 | ␉␉␉break;␊ |
71 | ␉}␊ |
72 | }␊ |
73 | ␊ |
74 | // patches a 64bit kernel.␊ |
75 | void patch_kernel_64(void* kernelData)␊ |
76 | {␊ |
77 | ␉// At the moment, the kernel patching code fails when used␊ |
78 | ␉// in 64bit mode, so we don't patch it. This is due to 32bit vs 64bit␊ |
79 | ␉// pointers as well as changes in structure sizes␊ |
80 | ␉printf("Unable to patch 64bit kernel. Please use arch=i386.\n");␊ |
81 | }␊ |
82 | ␊ |
83 | ␊ |
84 | /**␊ |
85 | ** patch_kernel_32␊ |
86 | **␉␉patches kernel based on cpu info determined earlier in the boot process.␊ |
87 | **␉␉It the machine is vmware, remove the artificial lapic panic␊ |
88 | **␉␉If the CPU is not supported, remove the cpuid_set_info panic␊ |
89 | **␉␉If the CPU is and Intel Atom, inject the penryn cpuid info.␊ |
90 | **/␊ |
91 | void patch_kernel_32(void* kernelData)␊ |
92 | {␊ |
93 | ␉// Remove panic in commpage␊ |
94 | ␉patch_commpage_stuff_routine(kernelData);␊ |
95 | ␉␊ |
96 | ␉//patch_pmCPUExitHaltToOff(kernelData);␉// Not working as intended, disabled for now␊ |
97 | ␉␊ |
98 | ␉//␉if(vmware_detected)␊ |
99 | ␉{␊ |
100 | ␉␉patch_lapic_init(kernelData);␊ |
101 | ␉}␊ |
102 | ␉␊ |
103 | ␉switch(13)//Platform.CPU.Model)␊ |
104 | ␉{␊ |
105 | ␉␉␉// Known good CPU's, no reason to patch kernel␊ |
106 | ␉␉case 13:␊ |
107 | ␉␉case CPUID_MODEL_YONAH:␊ |
108 | ␉␉case CPUID_MODEL_MEROM:␊ |
109 | ␉␉case CPUID_MODEL_PENRYN:␊ |
110 | ␉␉case CPUID_MODEL_NEHALEM:␊ |
111 | ␉␉case CPUID_MODEL_FIELDS:␊ |
112 | ␉␉case CPUID_MODEL_DALES:␊ |
113 | ␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
114 | ␉␉␉break;␊ |
115 | ␉␉␉␊ |
116 | ␉␉␉// Known unsuported CPU's␊ |
117 | ␉␉case CPUID_MODEL_ATOM:␊ |
118 | ␉␉␉// TODO: Impersonate CPU based on user selection␊ |
119 | ␉␉␉patch_cpuid_set_info(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␉// Impersonate Penryn CPU␊ |
120 | ␉␉␉break;␊ |
121 | ␉␉␉␊ |
122 | ␉␉␉// Unknown CPU's␊ |
123 | ␉␉default:␉␊ |
124 | ␉␉␉// TODO: Impersonate CPU based on user selection␊ |
125 | ␉␉␉patch_cpuid_set_info(kernelData, 0, 0);␉// Remove Panic Call␊ |
126 | ␉␉␉␊ |
127 | ␉␉␉break;␊ |
128 | ␉}␊ |
129 | }␊ |
130 | ␊ |
131 | ␊ |
132 | /**␊ |
133 | **␉␉This functions located the kernelSymbols[i] symbols in the mach-o header.␊ |
134 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
135 | **/␊ |
136 | int locate_symbols(void* kernelData)␊ |
137 | {␊ |
138 | ␉UInt16 symbolIndexes[NUM_SYMBOLS];␊ |
139 | ␊ |
140 | ␉struct load_command *loadCommand;␊ |
141 | ␉struct symtab_command *symtableData;␊ |
142 | ␉struct nlist *symbolEntry;␊ |
143 | ␉␊ |
144 | ␉char* symbolString;␊ |
145 | ␊ |
146 | ␉UInt32 kernelIndex = 0;␊ |
147 | ␉kernelIndex += sizeof(struct mach_header);␊ |
148 | ␉␊ |
149 | ␉if(((struct mach_header*)kernelData)->magic != MH_MAGIC) return KERNEL_64;␊ |
150 | ␉␊ |
151 | ␉␊ |
152 | ␉//printf("%d load commands beginning at 0x%X\n", (unsigned int)header->ncmds, (unsigned int)kernelIndex);␊ |
153 | ␉//printf("Commands take up %d bytes\n", header->sizeofcmds);␊ |
154 | ␉␊ |
155 | ␉␊ |
156 | ␉int cmd = 0;␊ |
157 | ␉while(cmd < ((struct mach_header*)kernelData)->ncmds)␉// TODO: for loop instead␊ |
158 | ␉{␊ |
159 | ␉␉cmd++;␊ |
160 | ␉␉␊ |
161 | ␉␉loadCommand = kernelData + kernelIndex;␊ |
162 | ␉␉␊ |
163 | ␉␉UInt cmdSize = loadCommand->cmdsize;␊ |
164 | ␉␉␊ |
165 | ␉␉␊ |
166 | ␉␉// Locate start of _panic and _cpuid_set_info in the symbol tabe.␊ |
167 | ␉␉// Load commands should be anded with 0x7FFFFFFF to ignore the␉LC_REQ_DYLD flag␊ |
168 | ␉␉if((loadCommand->cmd & 0x7FFFFFFF) == LC_SYMTAB)␉␉// We only care about the symtab segment␊ |
169 | ␉␉{␊ |
170 | ␉␉␉//printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData));␊ |
171 | ␉␉␉␊ |
172 | ␉␉␉symtableData = kernelData + kernelIndex;␊ |
173 | ␉␉␉kernelIndex += sizeof(struct symtab_command);␊ |
174 | ␉␉␉␊ |
175 | ␉␉␉cmdSize -= sizeof(struct symtab_command);␊ |
176 | ␊ |
177 | ␉␉␉// Loop through symbol table untill all of the symbols have been found␊ |
178 | ␉␉␉␊ |
179 | ␉␉␉symbolString = kernelData + symtableData->stroff; ␊ |
180 | ␉␉␉␊ |
181 | ␉␉␉␊ |
182 | ␉␉␉UInt16 symbolIndex = 0;␊ |
183 | ␉␉␉UInt8 numSymbolsFound = 0;␊ |
184 | ␊ |
185 | ␉␉␉while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS)␉// TODO: for loop␊ |
186 | ␉␉␉{␊ |
187 | ␉␉␉␉int i = 0;␊ |
188 | ␉␉␉␉while(i < NUM_SYMBOLS)␊ |
189 | ␉␉␉␉{␊ |
190 | ␉␉␉␉␉if(strcmp(symbolString, kernelSymbols[i]) == 0)␊ |
191 | ␉␉␉␉␉{␊ |
192 | ␉␉␉␉␉␉symbolIndexes[i] = symbolIndex;␊ |
193 | ␉␉␉␉␉␉numSymbolsFound++;␉␉␉␉␊ |
194 | ␉␉␉␉␉} ␊ |
195 | ␉␉␉␉␉i++;␊ |
196 | ␉␉␉␉␉␊ |
197 | ␉␉␉␉}␊ |
198 | ␉␉␉␉symbolString += strlen(symbolString) + 1;␊ |
199 | ␉␉␉␉symbolIndex++;␊ |
200 | ␉␉␉}␊ |
201 | ␉␉␉␊ |
202 | ␉␉␉// loop again␊ |
203 | ␉␉␉symbolIndex = 0;␊ |
204 | ␉␉␉numSymbolsFound = 0;␊ |
205 | ␉␉␉while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS)␉// TODO: for loop␊ |
206 | ␉␉␉{␊ |
207 | ␉␉␉␉␊ |
208 | ␉␉␉␉symbolEntry = kernelData + symtableData->symoff + (symbolIndex * sizeof(struct nlist));␊ |
209 | ␉␉␉␉␊ |
210 | ␉␉␉␉int i = 0;␊ |
211 | ␉␉␉␉while(i < NUM_SYMBOLS)␊ |
212 | ␉␉␉␉{␊ |
213 | ␉␉␉␉␉if(symbolIndex == (symbolIndexes[i] - 4))␊ |
214 | ␉␉␉␉␉{␊ |
215 | ␉␉␉␉␉␉kernelSymbolAddresses[i] = (UInt32)symbolEntry->n_value;␊ |
216 | ␉␉␉␉␉␉numSymbolsFound++;␉␉␉␉␊ |
217 | ␉␉␉␉␉} ␊ |
218 | ␉␉␉␉␉i++;␊ |
219 | ␉␉␉␉␉␊ |
220 | ␉␉␉␉}␊ |
221 | ␉␉␉␉␊ |
222 | ␉␉␉␉symbolIndex ++;␊ |
223 | ␉␉␉}␉␉␉␊ |
224 | ␉␉// Load commands should be anded with 0x7FFFFFFF to ignore the␉LC_REQ_DYLD flag␊ |
225 | ␉␉} else if((loadCommand->cmd & 0x7FFFFFFF) == LC_SEGMENT)␉␉// We only care about the __TEXT segment, any other load command can be ignored␊ |
226 | ␉␉{␊ |
227 | ␉␉␉␊ |
228 | ␉␉␉struct segment_command *segCommand;␊ |
229 | ␉␉␉␊ |
230 | ␉␉␉segCommand = kernelData + kernelIndex;␊ |
231 | ␉␉␉␊ |
232 | ␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
233 | ␉␉␉␊ |
234 | ␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
235 | ␉␉␉{␊ |
236 | ␉␉␉␉UInt32 sectionIndex;␊ |
237 | ␉␉␉␉␊ |
238 | ␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
239 | ␉␉␉␉␊ |
240 | ␉␉␉␉struct section *sect;␊ |
241 | ␉␉␉␉␊ |
242 | ␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
243 | ␉␉␉␉{␊ |
244 | ␉␉␉␉␉sect = kernelData + kernelIndex + sectionIndex;␊ |
245 | ␉␉␉␉␉␊ |
246 | ␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
247 | ␉␉␉␉␉␊ |
248 | ␉␉␉␉␉␊ |
249 | ␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
250 | ␉␉␉␉␉{␊ |
251 | ␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
252 | ␉␉␉␉␉␉textSection = sect->offset;␊ |
253 | ␉␉␉␉␉␉textAddress = sect->addr;␊ |
254 | ␉␉␉␉␉␉break;␊ |
255 | ␉␉␉␉␉}␉␉␉␉␉␊ |
256 | ␉␉␉␉}␊ |
257 | ␉␉␉}␊ |
258 | ␉␉␉␊ |
259 | ␉␉␉␊ |
260 | ␉␉␉kernelIndex += cmdSize;␊ |
261 | ␉␉} else {␊ |
262 | ␉␉␉kernelIndex += cmdSize;␊ |
263 | ␉␉}␊ |
264 | ␉}␊ |
265 | ␉␊ |
266 | ␉return KERNEL_32;␊ |
267 | }␊ |
268 | ␊ |
269 | ␊ |
270 | /**␊ |
271 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
272 | ** Or replace it so that the cpuid is set to a valid value.␊ |
273 | **/␊ |
274 | void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
275 | {␊ |
276 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
277 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
278 | ␉UInt32 jumpLocation = 0;␊ |
279 | ␉UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
280 | ␉if(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] == 0)␊ |
281 | ␉{␊ |
282 | ␉␉printf("Unable to locate _cpuid_set_info\n");␊ |
283 | ␉␉return;␊ |
284 | ␉␉␊ |
285 | ␉}␊ |
286 | ␉if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
287 | ␉{␊ |
288 | ␉␉printf("Unable to locate _panic\n");␊ |
289 | ␉␉return;␊ |
290 | ␉}␊ |
291 | ␉␊ |
292 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
293 | ␉while( ␊ |
294 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
295 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
296 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
297 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
298 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
299 | ␉␉ )␊ |
300 | ␉{␊ |
301 | ␉␉patchLocation++;␊ |
302 | ␉}␊ |
303 | ␉patchLocation--;␊ |
304 | ␉␊ |
305 | ␉␊ |
306 | ␉// Remove panic call, just in case the following patch routines fail␊ |
307 | ␉bytes[patchLocation + 0] = 0x90;␊ |
308 | ␉bytes[patchLocation + 1] = 0x90;␊ |
309 | ␉bytes[patchLocation + 2] = 0x90;␊ |
310 | ␉bytes[patchLocation + 3] = 0x90;␊ |
311 | ␉bytes[patchLocation + 4] = 0x90;␊ |
312 | ␉␊ |
313 | ␉␊ |
314 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
315 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
316 | ␉jumpLocation = patchLocation - 15;␊ |
317 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
318 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
319 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
320 | ␉{␊ |
321 | ␉␉jumpLocation--;␊ |
322 | ␉}␊ |
323 | ␉␊ |
324 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
325 | ␉if(impersonateFamily &&␊ |
326 | ␉ impersonateModel &&␊ |
327 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
328 | ␉{␊ |
329 | ␉␉␊ |
330 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
331 | ␉␉␊ |
332 | ␉␉/* ␊ |
333 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
334 | ␉␉ */␊ |
335 | ␊ |
336 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
337 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
338 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
339 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 8 |␊ |
340 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 16 |␊ |
341 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 24;␊ |
342 | ␉␉␊ |
343 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
344 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
345 | ␉␉␊ |
346 | ␉␉␊ |
347 | ␉␉// cpufamily = CPUFAMILY_INTEL_PENRYN␊ |
348 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
349 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
350 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
351 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
352 | ␉␉␊ |
353 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
354 | ␉␉// nop and continue with the rest of the patch␊ |
355 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
356 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
357 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
358 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
359 | ␉␉␊ |
360 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
361 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
362 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
363 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
364 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
365 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
366 | ␉␉␊ |
367 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
368 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
369 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
370 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
371 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
372 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
373 | ␉␉␊ |
374 | ␉}␊ |
375 | ␉else if(impersonateFamily && impersonateModel)␊ |
376 | ␉{␊ |
377 | ␉␉// pre 10.6.2 kernel␊ |
378 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
379 | ␉␉jumpLocation = patchLocation - 4;␊ |
380 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
381 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
382 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
383 | ␉␉{␊ |
384 | ␉␉␉jumpLocation--;␊ |
385 | ␉␉}␊ |
386 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
387 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
388 | ␉␉␊ |
389 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
390 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
391 | ␉␉// we set now.␊ |
392 | ␉␉␊ |
393 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
394 | ␉␉{␊ |
395 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
396 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 8 |␊ |
397 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 16 |␊ |
398 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 11] << 24);␊ |
399 | ␉␉␉// Remove jump␊ |
400 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
401 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
402 | ␊ |
403 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
404 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
405 | ␉␉␉␊ |
406 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
407 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
408 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
409 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
410 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
411 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
412 | ␉␉␉␊ |
413 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
414 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
415 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
416 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
417 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
418 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
419 | ␉␉␉␊ |
420 | ␉␉␉␊ |
421 | ␉␉␉␊ |
422 | ␉␉␉patchLocation = jumpLocation;␊ |
423 | ␉␉␉// We now have 14 bytes available for a patch␊ |
424 | ␉␉␉␊ |
425 | ␉␉}␊ |
426 | ␉␉else ␊ |
427 | ␉␉{␊ |
428 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
429 | ␉␉}␊ |
430 | ␉}␊ |
431 | ␉else ␊ |
432 | ␉{␊ |
433 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
434 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
435 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
436 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
437 | ␉}␊ |
438 | }␊ |
439 | ␊ |
440 | ␊ |
441 | /**␊ |
442 | ** SleepEnabler.kext replacement (for those that need it)␊ |
443 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
444 | **/␊ |
445 | void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
446 | {␊ |
447 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
448 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] - textAddress + textSection);␊ |
449 | ␊ |
450 | ␉if(kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] == 0)␊ |
451 | ␉{␊ |
452 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
453 | ␉␉return;␊ |
454 | ␉}␊ |
455 | ␉␊ |
456 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
457 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
458 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
459 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
460 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
461 | ␊ |
462 | ␉{␊ |
463 | ␉␉patchLocation++;␊ |
464 | ␉}␊ |
465 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
466 | }␊ |
467 | ␊ |
468 | void patch_lapic_init(void* kernelData)␊ |
469 | {␊ |
470 | ␉UInt8 panicIndex = 0;␊ |
471 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
472 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_LAPIC_INIT] - textAddress + textSection);␊ |
473 | ␉UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
474 | ␊ |
475 | ␉if(kernelSymbolAddresses[SYMBOL_LAPIC_INIT] == 0)␊ |
476 | ␉{␊ |
477 | ␉␉printf("Unable to locate %s\n", SYMBOL_LAPIC_INIT_STRING);␊ |
478 | ␉␉return;␊ |
479 | ␉␉␊ |
480 | ␉}␊ |
481 | ␉if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
482 | ␉{␊ |
483 | ␉␉printf("Unable to locate %s\n", SYMBOL_PANIC_STRING);␊ |
484 | ␉␉return;␊ |
485 | ␉}␊ |
486 | ␉␊ |
487 | ␉␊ |
488 | ␉␊ |
489 | ␉// Locate the (panicIndex + 1) panic call␊ |
490 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
491 | ␉{␊ |
492 | ␉␉while( ␊ |
493 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
494 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
495 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
496 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
497 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
498 | ␉␉␉ )␊ |
499 | ␉␉{␊ |
500 | ␉␉␉patchLocation++;␊ |
501 | ␉␉}␊ |
502 | ␉␉patchLocation++;␊ |
503 | ␉␉panicIndex++;␊ |
504 | ␉}␊ |
505 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
506 | ␉␊ |
507 | ␉bytes[--patchLocation] = 0x90;␉␊ |
508 | ␉bytes[++patchLocation] = 0x90;␊ |
509 | ␉bytes[++patchLocation] = 0x90;␊ |
510 | ␉bytes[++patchLocation] = 0x90;␊ |
511 | ␉bytes[++patchLocation] = 0x90;␊ |
512 | ␉␊ |
513 | ␉␊ |
514 | }␊ |
515 | ␊ |
516 | ␊ |
517 | void patch_commpage_stuff_routine(void* kernelData)␊ |
518 | {␊ |
519 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
520 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] - textAddress + textSection);␊ |
521 | ␉UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
522 | ␉␊ |
523 | ␉if(kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] == 0)␊ |
524 | ␉{␊ |
525 | ␉␉printf("Unable to locate %s\n", SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING);␊ |
526 | ␉␉return;␊ |
527 | ␉␉␊ |
528 | ␉}␊ |
529 | ␉if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
530 | ␉{␊ |
531 | ␉␉printf("Unable to locate %s\n", SYMBOL_PANIC_STRING);␊ |
532 | ␉␉return;␊ |
533 | ␉}␊ |
534 | ␉␊ |
535 | ␉␊ |
536 | ␉while( ␊ |
537 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
538 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
539 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
540 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
541 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
542 | ␉␉ )␊ |
543 | ␉{␊ |
544 | ␉␉patchLocation++;␊ |
545 | ␉}␊ |
546 | ␉patchLocation--;␊ |
547 | ␉␊ |
548 | ␉␊ |
549 | ␉// Remove panic call, just in case the following patch routines fail␊ |
550 | ␉bytes[patchLocation + 0] = 0x90;␊ |
551 | ␉bytes[patchLocation + 1] = 0x90;␊ |
552 | ␉bytes[patchLocation + 2] = 0x90;␊ |
553 | ␉bytes[patchLocation + 3] = 0x90;␊ |
554 | ␉bytes[patchLocation + 4] = 0x90;␊ |
555 | ␉␊ |
556 | ␉␊ |
557 | }␊ |
558 |