Root/
Source at commit 154 created 13 years 11 months ago. By meklort, Added a pacth_lapic_init routine. determines if a patch is required based on cpu model. Todo: make cpuid patch configurable | |
---|---|
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 NUM_SYMBOLS␉␉␉␉␉␉␉4␊ |
18 | ␊ |
19 | #define SYMBOL_CPUID_SET_INFO_STRING␉␉"_cpuid_set_info"␊ |
20 | #define SYMBOL_PANIC_STRING␉␉␉␉␉"_panic"␊ |
21 | #define SYMBOL_PMCPUEXITHALTTOOFF_STRING␉"_pmCPUExitHaltToOff"␊ |
22 | #define SYMBOL_LAPIC_INIT_STRING␉␉␉"_lapic_init"␊ |
23 | ␊ |
24 | char* kernelSymbols[NUM_SYMBOLS] = {␊ |
25 | ␉SYMBOL_CPUID_SET_INFO_STRING,␊ |
26 | ␉SYMBOL_PANIC_STRING,␊ |
27 | ␉SYMBOL_PMCPUEXITHALTTOOFF_STRING,␊ |
28 | ␉SYMBOL_LAPIC_INIT_STRING␊ |
29 | };␊ |
30 | ␊ |
31 | UInt32 kernelSymbolAddresses[NUM_SYMBOLS] = {␊ |
32 | ␉0,␊ |
33 | ␉0,␊ |
34 | ␉0,␊ |
35 | ␉0␊ |
36 | };␊ |
37 | ␊ |
38 | ␊ |
39 | UInt32 textSection = 0;␊ |
40 | UInt32 textAddress = 0;␊ |
41 | ␊ |
42 | ␊ |
43 | void patch_kernel(void* kernelData)␊ |
44 | {␊ |
45 | ␉switch (locate_symbols((void*)kernelData)) {␊ |
46 | ␉␉case KERNEL_32:␊ |
47 | ␉␉␉patch_kernel_32((void*)kernelData);␊ |
48 | ␉␉␉break;␊ |
49 | ␉␉␉␊ |
50 | ␉␉case KERNEL_64:␊ |
51 | ␉␉default:␊ |
52 | ␉␉␉patch_kernel_64((void*)kernelData);␊ |
53 | ␉␉␉break;␊ |
54 | ␉}␊ |
55 | }␊ |
56 | ␊ |
57 | // patches a 64bit kernel.␊ |
58 | void patch_kernel_64(void* kernelData)␊ |
59 | {␊ |
60 | ␉// At the moment, the kernel patching code fails when used␊ |
61 | ␉// in 64bit mode, so we don't patch it. This is due to 32bit vs 64bit␊ |
62 | ␉// pointers as well as changes in structure sizes␊ |
63 | ␉printf("Unable to patch 64bit kernel. Please use arch=i386.\n");␊ |
64 | }␊ |
65 | ␊ |
66 | ␊ |
67 | /**␊ |
68 | ** patch_kernel_32␊ |
69 | **␉␉patches kernel based on cpu info determined earlier in the boot process.␊ |
70 | **␉␉It the machine is vmware, remove the artificial lapic panic␊ |
71 | **␉␉If the CPU is not supported, remove the cpuid_set_info panic␊ |
72 | **␉␉If the CPU is and Intel Atom, inject the penryn cpuid info.␊ |
73 | **/␊ |
74 | void patch_kernel_32(void* kernelData)␊ |
75 | {␊ |
76 | ␉//patch_pmCPUExitHaltToOff(kernelData);␉// Not working as intended, disabled for now␊ |
77 | ␉␊ |
78 | ␉//␉if(vmware_detected)␊ |
79 | ␉{␊ |
80 | ␉␉patch_lapic_init(kernelData);␊ |
81 | ␉}␊ |
82 | ␉␊ |
83 | ␉switch( Platform.CPU.Vendor )␊ |
84 | ␉{␊ |
85 | ␉␉case 0x06:␊ |
86 | ␉␉␉switch(Platform.CPU.Model)␊ |
87 | ␉␉␉{␊ |
88 | ␉␉␉␉// Known good CPU's, no reason to patch kernel␊ |
89 | ␉␉␉␉case 13:␊ |
90 | ␉␉␉␉case CPUID_MODEL_YONAH:␊ |
91 | ␉␉␉␉case CPUID_MODEL_MEROM:␊ |
92 | ␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
93 | ␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
94 | ␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
95 | ␉␉␉␉case CPUID_MODEL_DALES:␊ |
96 | ␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
97 | ␉␉␉␉␉break;␊ |
98 | ␉␉␉␉␉␊ |
99 | ␉␉␉␉// Known unsuported CPU's␊ |
100 | ␉␉␉␉case CPUID_MODEL_ATOM:␊ |
101 | ␉␉␉␉␉// TODO: Impersonate CPU based on user selection␊ |
102 | ␉␉␉␉␉patch_cpuid_set_info(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);␉// Impersonate Penryn CPU␊ |
103 | ␉␉␉␉␉break;␊ |
104 | ␉␉␉␉␉␊ |
105 | ␉␉␉␉// Unknown CPU's␊ |
106 | ␉␉␉␉default:␉␊ |
107 | ␉␉␉␉␉// TODO: Impersonate CPU based on user selection␊ |
108 | ␉␉␉␉␉patch_cpuid_set_info(kernelData, 0, 0);␉// Remove Panic Call␊ |
109 | ␊ |
110 | ␉␉␉␉␉break;␊ |
111 | ␉␉␉}␊ |
112 | ␉␉␉break;␊ |
113 | ␉␉␉␊ |
114 | ␉␉default:␊ |
115 | ␉␉␉break;␊ |
116 | ␉}␊ |
117 | }␊ |
118 | ␊ |
119 | ␊ |
120 | /**␊ |
121 | **␉␉This functions located the kernelSymbols[i] symbols in the macho header.␊ |
122 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
123 | **/␊ |
124 | int locate_symbols(void* kernelData)␊ |
125 | {␊ |
126 | ␉UInt16 symbolIndexes[NUM_SYMBOLS];␊ |
127 | ␊ |
128 | ␉struct load_command *loadCommand;␊ |
129 | ␉struct symtab_command *symtableData;␊ |
130 | ␉struct nlist *symbolEntry;␊ |
131 | ␉␊ |
132 | ␉char* symbolString;␊ |
133 | ␊ |
134 | ␉UInt32 kernelIndex = 0;␊ |
135 | ␉kernelIndex += sizeof(struct mach_header);␊ |
136 | ␉␊ |
137 | ␉if(((struct mach_header*)kernelData)->magic != MH_MAGIC) return KERNEL_64;␊ |
138 | ␉␊ |
139 | ␉␊ |
140 | ␉//printf("%d load commands beginning at 0x%X\n", (unsigned int)header->ncmds, (unsigned int)kernelIndex);␊ |
141 | ␉//printf("Commands take up %d bytes\n", header->sizeofcmds);␊ |
142 | ␉␊ |
143 | ␉␊ |
144 | ␉int cmd = 0;␊ |
145 | ␉while(cmd < ((struct mach_header*)kernelData)->ncmds)␉// TODO: for loop instead␊ |
146 | ␉{␊ |
147 | ␉␉cmd++;␊ |
148 | ␉␉␊ |
149 | ␉␉loadCommand = kernelData + kernelIndex;␊ |
150 | ␉␉␊ |
151 | ␉␉UInt cmdSize = loadCommand->cmdsize;␊ |
152 | ␉␉␊ |
153 | ␉␉␊ |
154 | ␉␉// Locate start of _panic and _cpuid_set_info in the symbol tabe.␊ |
155 | ␉␉// Load commands should be anded with 0x7FFFFFFF to ignore the␉LC_REQ_DYLD flag␊ |
156 | ␉␉if((loadCommand->cmd & 0x7FFFFFFF) == LC_SYMTAB)␉␉// We only care about the symtab segment␊ |
157 | ␉␉{␊ |
158 | ␉␉␉//printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData));␊ |
159 | ␉␉␉␊ |
160 | ␉␉␉symtableData = kernelData + kernelIndex;␊ |
161 | ␉␉␉kernelIndex += sizeof(struct symtab_command);␊ |
162 | ␉␉␉␊ |
163 | ␉␉␉cmdSize -= sizeof(struct symtab_command);␊ |
164 | ␊ |
165 | ␉␉␉// Loop through symbol table untill all of the symbols have been found␊ |
166 | ␉␉␉␊ |
167 | ␉␉␉symbolString = kernelData + symtableData->stroff; ␊ |
168 | ␉␉␉␊ |
169 | ␉␉␉␊ |
170 | ␉␉␉UInt16 symbolIndex = 0;␊ |
171 | ␉␉␉UInt8 numSymbolsFound = 0;␊ |
172 | ␊ |
173 | ␉␉␉while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS)␉// TODO: for loop␊ |
174 | ␉␉␉{␊ |
175 | ␉␉␉␉int i = 0;␊ |
176 | ␉␉␉␉while(i < NUM_SYMBOLS)␊ |
177 | ␉␉␉␉{␊ |
178 | ␉␉␉␉␉if(strcmp(symbolString, kernelSymbols[i]) == 0)␊ |
179 | ␉␉␉␉␉{␊ |
180 | ␉␉␉␉␉␉symbolIndexes[i] = symbolIndex;␊ |
181 | ␉␉␉␉␉␉numSymbolsFound++;␉␉␉␉␊ |
182 | ␉␉␉␉␉} ␊ |
183 | ␉␉␉␉␉i++;␊ |
184 | ␉␉␉␉␉␊ |
185 | ␉␉␉␉}␊ |
186 | ␉␉␉␉symbolString += strlen(symbolString) + 1;␊ |
187 | ␉␉␉␉symbolIndex++;␊ |
188 | ␉␉␉}␊ |
189 | ␉␉␉␊ |
190 | ␉␉␉// loop again␊ |
191 | ␉␉␉symbolIndex = 0;␊ |
192 | ␉␉␉numSymbolsFound = 0;␊ |
193 | ␉␉␉while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS)␉// TODO: for loop␊ |
194 | ␉␉␉{␊ |
195 | ␉␉␉␉␊ |
196 | ␉␉␉␉symbolEntry = kernelData + symtableData->symoff + (symbolIndex * sizeof(struct nlist));␊ |
197 | ␉␉␉␉␊ |
198 | ␉␉␉␉int i = 0;␊ |
199 | ␉␉␉␉while(i < NUM_SYMBOLS)␊ |
200 | ␉␉␉␉{␊ |
201 | ␉␉␉␉␉if(symbolIndex == (symbolIndexes[i] - 4))␊ |
202 | ␉␉␉␉␉{␊ |
203 | ␉␉␉␉␉␉kernelSymbolAddresses[i] = (UInt32)symbolEntry->n_value;␊ |
204 | ␉␉␉␉␉␉numSymbolsFound++;␉␉␉␉␊ |
205 | ␉␉␉␉␉} ␊ |
206 | ␉␉␉␉␉i++;␊ |
207 | ␉␉␉␉␉␊ |
208 | ␉␉␉␉}␊ |
209 | ␉␉␉␉␊ |
210 | ␉␉␉␉symbolIndex ++;␊ |
211 | ␉␉␉}␉␉␉␊ |
212 | ␉␉// Load commands should be anded with 0x7FFFFFFF to ignore the␉LC_REQ_DYLD flag␊ |
213 | ␉␉} else if((loadCommand->cmd & 0x7FFFFFFF) == LC_SEGMENT)␉␉// We only care about the __TEXT segment, any other load command can be ignored␊ |
214 | ␉␉{␊ |
215 | ␉␉␉␊ |
216 | ␉␉␉struct segment_command *segCommand;␊ |
217 | ␉␉␉␊ |
218 | ␉␉␉segCommand = kernelData + kernelIndex;␊ |
219 | ␉␉␉␊ |
220 | ␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
221 | ␉␉␉␊ |
222 | ␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
223 | ␉␉␉{␊ |
224 | ␉␉␉␉UInt32 sectionIndex;␊ |
225 | ␉␉␉␉␊ |
226 | ␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
227 | ␉␉␉␉␊ |
228 | ␉␉␉␉struct section *sect;␊ |
229 | ␉␉␉␉␊ |
230 | ␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
231 | ␉␉␉␉{␊ |
232 | ␉␉␉␉␉sect = kernelData + kernelIndex + sectionIndex;␊ |
233 | ␉␉␉␉␉␊ |
234 | ␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
235 | ␉␉␉␉␉␊ |
236 | ␉␉␉␉␉␊ |
237 | ␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
238 | ␉␉␉␉␉{␊ |
239 | ␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
240 | ␉␉␉␉␉␉textSection = sect->offset;␊ |
241 | ␉␉␉␉␉␉textAddress = sect->addr;␊ |
242 | ␉␉␉␉␉␉break;␊ |
243 | ␉␉␉␉␉}␉␉␉␉␉␊ |
244 | ␉␉␉␉}␊ |
245 | ␉␉␉}␊ |
246 | ␉␉␉␊ |
247 | ␉␉␉␊ |
248 | ␉␉␉kernelIndex += cmdSize;␊ |
249 | ␉␉} else {␊ |
250 | ␉␉␉kernelIndex += cmdSize;␊ |
251 | ␉␉}␊ |
252 | ␉}␊ |
253 | ␉␊ |
254 | ␉return KERNEL_32;␊ |
255 | }␊ |
256 | ␊ |
257 | ␊ |
258 | /**␊ |
259 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
260 | ** Or replace it so that the cpuid is set to a valid value.␊ |
261 | **/␊ |
262 | void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 inpersonateModel)␊ |
263 | {␊ |
264 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
265 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
266 | ␉UInt32 jumpLocation = 0;␊ |
267 | ␉UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
268 | ␉if(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] == 0)␊ |
269 | ␉{␊ |
270 | ␉␉printf("Unable to locate _cpuid_set_info\n");␊ |
271 | ␉␉return;␊ |
272 | ␉␉␊ |
273 | ␉}␊ |
274 | ␉if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
275 | ␉{␊ |
276 | ␉␉printf("Unable to locate _panic\n");␊ |
277 | ␉␉return;␊ |
278 | ␉}␊ |
279 | ␉␊ |
280 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
281 | ␉while( ␊ |
282 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
283 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
284 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
285 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
286 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
287 | ␉␉ )␊ |
288 | ␉{␊ |
289 | ␉␉patchLocation++;␊ |
290 | ␉}␊ |
291 | ␉patchLocation--;␊ |
292 | ␉␊ |
293 | ␉␊ |
294 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
295 | ␉jumpLocation = patchLocation - 15;␊ |
296 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
297 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
298 | ␉␉ (patchLocation - jumpLocation) < 0xEF)␊ |
299 | ␉{␊ |
300 | ␉␉jumpLocation--;␊ |
301 | ␉}␊ |
302 | ␉␊ |
303 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
304 | ␉if(impersonateFamily &&␊ |
305 | ␉ inpersonateModel &&␊ |
306 | ␉ ((patchLocation - jumpLocation) < 0xEF))␊ |
307 | ␉{␊ |
308 | ␉␉␊ |
309 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
310 | ␉␉␊ |
311 | ␉␉/* ␊ |
312 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
313 | ␉␉ */␊ |
314 | ␊ |
315 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
316 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
317 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
318 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 8 |␊ |
319 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 16 |␊ |
320 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 24;␊ |
321 | ␉␉␊ |
322 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
323 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
324 | ␉␉␊ |
325 | ␉␉␊ |
326 | ␉␉// cpufamily = CPUFAMILY_INTEL_PENRYN␊ |
327 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
328 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
329 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
330 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
331 | ␉␉␊ |
332 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
333 | ␉␉// nop and continue with the rest of the patch␊ |
334 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
335 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
336 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
337 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
338 | ␉␉␊ |
339 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
340 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
341 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
342 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
343 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
344 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
345 | ␉␉␊ |
346 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
347 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
348 | ␉␉bytes[patchLocation + 1] = inpersonateModel;␉// cpuid_model␊ |
349 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
350 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
351 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
352 | ␉␉␊ |
353 | ␉}␊ |
354 | ␉else ␊ |
355 | ␉{␊ |
356 | ␉␉// Either We were unable to change the jump call due to the funciton's sctructure␊ |
357 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
358 | ␉␉// removing the panic call. Note that the IntelCPUPM kext may still panic ␊ |
359 | ␉␉// due to the cpu's Model ID not being patched␊ |
360 | ␉␉bytes[patchLocation + 0] = 0x90;␊ |
361 | ␉␉bytes[patchLocation + 1] = 0x90;␊ |
362 | ␉␉bytes[patchLocation + 2] = 0x90;␊ |
363 | ␉␉bytes[patchLocation + 3] = 0x90;␊ |
364 | ␉␉bytes[patchLocation + 4] = 0x90;␊ |
365 | ␉␉␊ |
366 | ␉}␊ |
367 | }␊ |
368 | ␊ |
369 | ␊ |
370 | /**␊ |
371 | ** SleepEnabler.kext replacement (for those that need it)␊ |
372 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
373 | **/␊ |
374 | void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
375 | {␊ |
376 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
377 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] - textAddress + textSection);␊ |
378 | ␊ |
379 | ␉if(kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] == 0)␊ |
380 | ␉{␊ |
381 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
382 | ␉␉return;␊ |
383 | ␉}␊ |
384 | ␉␊ |
385 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
386 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
387 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
388 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
389 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
390 | ␊ |
391 | ␉{␊ |
392 | ␉␉patchLocation++;␊ |
393 | ␉}␊ |
394 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
395 | }␊ |
396 | ␊ |
397 | void patch_lapic_init(void* kernelData)␊ |
398 | {␊ |
399 | ␉UInt8 panicIndex = 0;␊ |
400 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
401 | ␉UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_LAPIC_INIT] - textAddress + textSection);␊ |
402 | ␉UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
403 | ␊ |
404 | ␉if(kernelSymbolAddresses[SYMBOL_LAPIC_INIT] == 0)␊ |
405 | ␉{␊ |
406 | ␉␉printf("Unable to locate _cpuid_set_info\n");␊ |
407 | ␉␉return;␊ |
408 | ␉␉␊ |
409 | ␉}␊ |
410 | ␉if(kernelSymbolAddresses[SYMBOL_PANIC] == 0)␊ |
411 | ␉{␊ |
412 | ␉␉printf("Unable to locate _panic\n");␊ |
413 | ␉␉return;␊ |
414 | ␉}␊ |
415 | ␉␊ |
416 | ␉␊ |
417 | ␉␊ |
418 | ␉// Locate the (panicIndex + 1) panic call␊ |
419 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
420 | ␉{␊ |
421 | ␉␉while( ␊ |
422 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
423 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
424 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
425 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
426 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
427 | ␉␉␉ )␊ |
428 | ␉␉{␊ |
429 | ␉␉␉patchLocation++;␊ |
430 | ␉␉}␊ |
431 | ␉␉patchLocation++;␊ |
432 | ␉␉panicIndex++;␊ |
433 | ␉}␊ |
434 | ␉bytes[--patchLocation] = 0x90;␊ |
435 | ␉bytes[++patchLocation] = 0x90;␊ |
436 | ␉bytes[++patchLocation] = 0x90;␊ |
437 | ␉bytes[++patchLocation] = 0x90;␊ |
438 | ␉bytes[++patchLocation] = 0x90;␊ |
439 | ␉␊ |
440 | ␉␊ |
441 | }␊ |
442 |