Root/
Source at commit 491 created 13 years 7 months ago. By meklort, Initial 64bit support. lapic_configure patch is currently 32bit only, however the rest of the patches should work fine on a 64bit kernel. I haven't teted this extensivly, so it may or may not work for everyone. | |
---|---|
1 | ␉/*␊ |
2 | * Copyright (c) 2009-2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "kernel_patcher.h"␊ |
8 | #include "platform.h"␊ |
9 | #include "modules.h"␊ |
10 | extern PlatformInfo_t Platform;␊ |
11 | ␊ |
12 | patchRoutine_t* patches = NULL;␊ |
13 | kernSymbols_t* kernelSymbols = NULL;␊ |
14 | ␊ |
15 | unsigned long long textAddress = 0;␊ |
16 | unsigned long long textSection = 0;␊ |
17 | //UInt64 vmaddr = 0;␊ |
18 | ␊ |
19 | void KernelPatcher_start()␊ |
20 | {␊ |
21 | ␉//register_kernel_patch(patch_cpuid_set_info, KERNEL_32, CPUID_MODEL_ATOM);␉␉// TODO: CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN␊ |
22 | ␉//register_kernel_patch(patch_cpuid_set_info, KERNEL_32, CPUID_MODEL_UNKNOWN);␉// 0, 0 ␊ |
23 | ␉register_kernel_patch(patch_cpuid_set_info_all, KERNEL_ANY, CPUID_MODEL_UNKNOWN); ␊ |
24 | ␊ |
25 | ␉register_kernel_patch(patch_commpage_stuff_routine, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
26 | ␉␊ |
27 | ␉register_kernel_patch(patch_lapic_init, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
28 | ␊ |
29 | ␉// NOTE: following is currently 32bit only␊ |
30 | ␉register_kernel_patch(patch_lapic_configure, KERNEL_32, CPUID_MODEL_ANY);␊ |
31 | ␊ |
32 | ␉␊ |
33 | ␉register_kernel_symbol(KERNEL_ANY, "_panic");␊ |
34 | ␉register_kernel_symbol(KERNEL_ANY, "_cpuid_set_info");␊ |
35 | ␉register_kernel_symbol(KERNEL_ANY, "_pmCPUExitHaltToOff");␊ |
36 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_init");␊ |
37 | ␉register_kernel_symbol(KERNEL_ANY, "_commpage_stuff_routine");␊ |
38 | ␊ |
39 | ␉// LAPIC configure symbols␊ |
40 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_configure");␊ |
41 | ␊ |
42 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_start");␊ |
43 | ␉register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base");␊ |
44 | ␉␊ |
45 | ␉␊ |
46 | ␉//register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY);␊ |
47 | ␉//register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt");␊ |
48 | ␊ |
49 | ␊ |
50 | ␉␊ |
51 | ␉// TODO: register needed symbols␊ |
52 | ␉␊ |
53 | ␉␊ |
54 | ␉register_hook_callback("ExecKernel", &patch_kernel); ␊ |
55 | }␊ |
56 | ␊ |
57 | /*␊ |
58 | * Register a kerenl patch␊ |
59 | */␊ |
60 | void register_kernel_patch(void* patch, int arch, int cpus)␊ |
61 | {␊ |
62 | ␉// TODO: only insert valid patches based on current cpuid and architecture␊ |
63 | ␉// AKA, don't at 64bit patches if it's a 32bit only machine␊ |
64 | ␉patchRoutine_t* entry;␊ |
65 | ␉␊ |
66 | ␉// TODO: verify Platform.CPU.Model is populated this early in bootup␊ |
67 | ␉// Check to ensure that the patch is valid on this machine␊ |
68 | ␉// If it is not, exit early form this function␊ |
69 | ␉if(cpus != Platform.CPU.Model)␊ |
70 | ␉{␊ |
71 | ␉␉if(cpus != CPUID_MODEL_ANY)␊ |
72 | ␉␉{␊ |
73 | ␉␉␉if(cpus == CPUID_MODEL_UNKNOWN)␊ |
74 | ␉␉␉{␊ |
75 | ␉␉␉␉switch(Platform.CPU.Model)␊ |
76 | ␉␉␉␉{␊ |
77 | ␉␉␉␉␉case 13:␊ |
78 | ␉␉␉␉␉case CPUID_MODEL_YONAH:␊ |
79 | ␉␉␉␉␉case CPUID_MODEL_MEROM:␊ |
80 | ␉␉␉␉␉case CPUID_MODEL_PENRYN:␊ |
81 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM:␊ |
82 | ␉␉␉␉␉case CPUID_MODEL_FIELDS:␊ |
83 | ␉␉␉␉␉case CPUID_MODEL_DALES:␊ |
84 | ␉␉␉␉␉case CPUID_MODEL_NEHALEM_EX:␊ |
85 | ␉␉␉␉␉␉// Known cpu's we don't want to add the patch␊ |
86 | ␉␉␉␉␉␉return;␊ |
87 | ␉␉␉␉␉␉break;␊ |
88 | ␊ |
89 | ␉␉␉␉␉default:␊ |
90 | ␉␉␉␉␉␉// CPU not in supported list, so we are going to add␊ |
91 | ␉␉␉␉␉␉// The patch will be applied␊ |
92 | ␉␉␉␉␉␉break;␊ |
93 | ␉␉␉␉␉␉␊ |
94 | ␉␉␉␉}␊ |
95 | ␉␉␉}␊ |
96 | ␉␉␉else␊ |
97 | ␉␉␉{␊ |
98 | ␉␉␉␉// Invalid cpuid for current cpu. Ignoring patch␊ |
99 | ␉␉␉␉return;␊ |
100 | ␉␉␉}␊ |
101 | ␊ |
102 | ␉␉}␊ |
103 | ␉}␊ |
104 | ␉␉␊ |
105 | ␉if(patches == NULL)␊ |
106 | ␉{␊ |
107 | ␉␉patches = entry = malloc(sizeof(patchRoutine_t));␊ |
108 | ␉}␊ |
109 | ␉else␊ |
110 | ␉{␊ |
111 | ␉␉entry = patches;␊ |
112 | ␉␉while(entry->next)␊ |
113 | ␉␉{␊ |
114 | ␉␉␉entry = entry->next;␊ |
115 | ␉␉}␊ |
116 | ␉␉␊ |
117 | ␉␉entry->next = malloc(sizeof(patchRoutine_t));␊ |
118 | ␉␉entry = entry->next;␊ |
119 | ␉}␊ |
120 | ␉␊ |
121 | ␉entry->next = NULL;␊ |
122 | ␉entry->patchRoutine = patch;␊ |
123 | ␉entry->validArchs = arch;␊ |
124 | ␉entry->validCpu = cpus;␊ |
125 | }␊ |
126 | ␊ |
127 | void register_kernel_symbol(int kernelType, const char* name)␊ |
128 | {␊ |
129 | ␉if(kernelSymbols == NULL)␊ |
130 | ␉{␊ |
131 | ␉␉kernelSymbols = malloc(sizeof(kernSymbols_t));␊ |
132 | ␉␉kernelSymbols->next = NULL;␊ |
133 | ␉␉kernelSymbols->symbol = (char*)name;␊ |
134 | ␉␉kernelSymbols->addr = 0;␊ |
135 | ␉}␊ |
136 | ␉else {␊ |
137 | ␉␉kernSymbols_t *symbol = kernelSymbols;␊ |
138 | ␉␉while(symbol->next != NULL)␊ |
139 | ␉␉{␊ |
140 | ␉␉␉symbol = symbol->next;␊ |
141 | ␉␉}␊ |
142 | ␉␉␊ |
143 | ␉␉symbol->next = malloc(sizeof(kernSymbols_t));␊ |
144 | ␉␉symbol = symbol->next;␊ |
145 | ␊ |
146 | ␉␉symbol->next = NULL;␊ |
147 | ␉␉symbol->symbol = (char*)name;␊ |
148 | ␉␉symbol->addr = 0;␊ |
149 | ␉}␊ |
150 | }␊ |
151 | ␊ |
152 | kernSymbols_t* lookup_kernel_symbol(const char* name)␊ |
153 | {␊ |
154 | ␉kernSymbols_t *symbol = kernelSymbols;␊ |
155 | ␊ |
156 | ␉while(symbol && strcmp(symbol->symbol, name) !=0)␊ |
157 | ␉{␊ |
158 | ␉␉symbol = symbol->next;␊ |
159 | ␉}␊ |
160 | ␉␊ |
161 | ␉if(!symbol)␊ |
162 | ␉{␊ |
163 | ␉␉return NULL;␊ |
164 | ␉}␊ |
165 | ␉else␊ |
166 | ␉{␊ |
167 | ␉␉return symbol;␊ |
168 | ␉}␊ |
169 | ␊ |
170 | }␊ |
171 | ␊ |
172 | void patch_kernel(void* kernelData, void* arg2, void* arg3, void *arg4)␊ |
173 | {␊ |
174 | ␉patchRoutine_t* entry = patches;␊ |
175 | ␊ |
176 | ␉␊ |
177 | ␉int arch = determineKernelArchitecture(kernelData);␊ |
178 | ␊ |
179 | ␉locate_symbols(kernelData);␊ |
180 | ␉␊ |
181 | ␉␊ |
182 | ␉if(patches != NULL)␊ |
183 | ␉{␊ |
184 | ␉␉while(entry)␊ |
185 | ␉␉{␊ |
186 | ␉␉␉if(entry->validArchs == KERNEL_ANY || arch == entry->validArchs)␊ |
187 | ␉␉␉{␊ |
188 | ␉␉␉␉if(entry->patchRoutine) entry->patchRoutine(kernelData);␊ |
189 | ␉␉␉}␊ |
190 | ␉␉␉entry = entry->next;␊ |
191 | ␉␉}␊ |
192 | ␉␉␊ |
193 | ␉}␊ |
194 | }␊ |
195 | ␊ |
196 | int determineKernelArchitecture(void* kernelData)␊ |
197 | {␉␊ |
198 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC)␊ |
199 | ␉{␊ |
200 | ␉␉return KERNEL_32;␊ |
201 | ␉}␊ |
202 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC_64)␊ |
203 | ␉{␊ |
204 | ␉␉return KERNEL_64;␊ |
205 | ␉}␊ |
206 | ␉else␊ |
207 | ␉{␊ |
208 | ␉␉return KERNEL_ERR;␊ |
209 | ␉}␊ |
210 | }␊ |
211 | ␊ |
212 | ␊ |
213 | /**␊ |
214 | **␉␉This functions located the requested symbols in the mach-o file.␊ |
215 | **␉␉␉as well as determines the start of the __TEXT segment and __TEXT,__text sections␊ |
216 | **/␊ |
217 | int locate_symbols(void* kernelData)␊ |
218 | {␊ |
219 | ␉char is64;␊ |
220 | ␉struct load_command *loadCommand;␊ |
221 | ␉struct symtab_command *symtableData = NULL;␊ |
222 | ␉struct segment_command *segCommand = NULL;␊ |
223 | ␉struct segment_command_64 *segCommand64 = NULL;␊ |
224 | ␊ |
225 | ␉UInt32 kernelIndex = 0;␊ |
226 | ␉␊ |
227 | ␉if(((struct mach_header*)kernelData)->magic == MH_MAGIC)␊ |
228 | ␉{␊ |
229 | ␉␉is64 = 0;␊ |
230 | ␉␉kernelIndex += sizeof(struct mach_header);␊ |
231 | ␊ |
232 | ␉}␊ |
233 | ␉else if(((struct mach_header_64*)kernelData)->magic == MH_MAGIC_64)␊ |
234 | ␉{␊ |
235 | ␉␉is64 = 1;␊ |
236 | ␉␉kernelIndex += sizeof(struct mach_header_64);␊ |
237 | ␊ |
238 | ␉}␊ |
239 | ␉else␊ |
240 | ␉{␊ |
241 | ␉␉printf("Invalid mach magic 0x%X\n", ((struct mach_header*)kernelData)->magic);␊ |
242 | ␉␉getc();␊ |
243 | ␉␉return KERNEL_ERR;␊ |
244 | ␉}␊ |
245 | ␉␊ |
246 | ␉␊ |
247 | ␉int cmd = 0;␊ |
248 | ␉while(cmd < ((struct mach_header*)kernelData)->ncmds)␉// TODO: for loop instead␊ |
249 | ␉{␊ |
250 | ␉␉cmd++;␊ |
251 | ␉␉␊ |
252 | ␉␉loadCommand = kernelData + kernelIndex;␊ |
253 | ␉␉␊ |
254 | ␉␉UInt cmdSize = loadCommand->cmdsize;␊ |
255 | ␉␉␊ |
256 | ␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
257 | ␉␉{␊ |
258 | ␉␉␉case LC_SYMTAB:␊ |
259 | ␉␉␉␉//printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData));␊ |
260 | ␉␉␉␉symtableData = kernelData + kernelIndex;␉␉␉␉␊ |
261 | ␉␉␉␉break;␊ |
262 | ␉␉␉␉␊ |
263 | ␉␉␉case LC_SEGMENT: // 32bit macho␊ |
264 | ␉␉␉␉segCommand = kernelData + kernelIndex;␊ |
265 | ␉␉␉␉␊ |
266 | ␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
267 | ␉␉␉␉␊ |
268 | ␉␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
269 | ␉␉␉␉{␊ |
270 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
271 | ␉␉␉␉␉␊ |
272 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
273 | ␉␉␉␉␉␊ |
274 | ␉␉␉␉␉struct section *sect;␊ |
275 | ␉␉␉␉␉␊ |
276 | ␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
277 | ␉␉␉␉␉{␊ |
278 | ␉␉␉␉␉␉sect = kernelData + kernelIndex + sectionIndex;␊ |
279 | ␉␉␉␉␉␉␊ |
280 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
281 | ␉␉␉␉␉␉␊ |
282 | ␉␉␉␉␉␉␊ |
283 | ␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
284 | ␉␉␉␉␉␉{␊ |
285 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
286 | ␉␉␉␉␉␉␉textSection = sect->offset;␊ |
287 | ␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
288 | ␉␉␉␉␉␉␉break;␊ |
289 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
290 | ␉␉␉␉␉}␊ |
291 | ␉␉␉␉}␊ |
292 | ␉␉␉␉break;␊ |
293 | ␉␉␉case LC_SEGMENT_64:␉// 64bit macho's␊ |
294 | ␉␉␉␉segCommand64 = kernelData + kernelIndex;␊ |
295 | ␉␉␉␉␊ |
296 | ␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
297 | ␉␉␉␉␊ |
298 | ␉␉␉␉if(strcmp("__TEXT", segCommand64->segname) == 0)␊ |
299 | ␉␉␉␉{␊ |
300 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
301 | ␉␉␉␉␉␊ |
302 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
303 | ␉␉␉␉␉␊ |
304 | ␉␉␉␉␉struct section_64 *sect;␊ |
305 | ␉␉␉␉␉␊ |
306 | ␉␉␉␉␉while(sectionIndex < segCommand64->cmdsize)␊ |
307 | ␉␉␉␉␉{␊ |
308 | ␉␉␉␉␉␉sect = kernelData + kernelIndex + sectionIndex;␊ |
309 | ␉␉␉␉␉␉␊ |
310 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section_64);␊ |
311 | ␉␉␉␉␉␉␊ |
312 | ␉␉␉␉␉␉␊ |
313 | ␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
314 | ␉␉␉␉␉␉{␊ |
315 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
316 | ␉␉␉␉␉␉␉textSection = sect->offset;␊ |
317 | ␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
318 | ␊ |
319 | ␉␉␉␉␉␉␉break;␊ |
320 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
321 | ␉␉␉␉␉}␊ |
322 | ␉␉␉␉}␊ |
323 | ␉␉␉␉␊ |
324 | ␉␉␉␉break;␊ |
325 | ␉␉␉␉␊ |
326 | ␉␉␉default:␊ |
327 | ␉␉␉␉break;␊ |
328 | ␉␉␉␉␊ |
329 | ␉␉}␊ |
330 | ␉␉kernelIndex += cmdSize;␊ |
331 | ␉}␊ |
332 | ␉handle_symtable((UInt32)kernelData, symtableData, &symbol_handler, determineKernelArchitecture(kernelData) == KERNEL_64);␊ |
333 | ␉return 1 << is64;␊ |
334 | }␊ |
335 | ␊ |
336 | long long symbol_handler(char* symbolName, long long addr, char is64)␊ |
337 | {␊ |
338 | ␉// Locate the symbol in the list, if it exists, update it's address␊ |
339 | ␉kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);␊ |
340 | ␉␊ |
341 | ␉␊ |
342 | ␉␊ |
343 | ␉if(symbol)␊ |
344 | ␉{␊ |
345 | ␊ |
346 | ␉␉//printf("Located %sbit symbol %s at 0x%lX\n", is64 ? "64" : "32", symbolName, addr);␊ |
347 | ␉␉//getc();␊ |
348 | ␉␉␊ |
349 | ␉␉symbol->addr = addr;␊ |
350 | ␉}␊ |
351 | ␉return 0xFFFFFFFF; // fixme␊ |
352 | }␊ |
353 | ␊ |
354 | ␊ |
355 | /**␊ |
356 | ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it␊ |
357 | ** Or replace it so that the cpuid is set to a valid value.␊ |
358 | **/␊ |
359 | void patch_cpuid_set_info_all(void* kernelData)␊ |
360 | {␊ |
361 | ␉switch(Platform.CPU.Model)␊ |
362 | ␉{␊ |
363 | ␉␉case CPUID_MODEL_ATOM:␊ |
364 | ␉␉␉patch_cpuid_set_info(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); ␊ |
365 | ␉␉␉break;␊ |
366 | ␉␉␉␊ |
367 | ␉␉default:␊ |
368 | ␉␉␉patch_cpuid_set_info(kernelData, 0, 0);␊ |
369 | ␉␉␉break;␊ |
370 | ␉}␊ |
371 | }␊ |
372 | ␊ |
373 | void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)␊ |
374 | {␉␊ |
375 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
376 | ␉␊ |
377 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");␊ |
378 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //␉(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);␊ |
379 | ␉␊ |
380 | ␉UInt32 jumpLocation = 0;␊ |
381 | ␉␊ |
382 | ␉␊ |
383 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
384 | ␉{␊ |
385 | ␉␉printf("Unable to locate _cpuid_set_info\n");␊ |
386 | ␉␉return;␊ |
387 | ␉␉␊ |
388 | ␉}␊ |
389 | ␊ |
390 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
391 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;␊ |
392 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
393 | ␉{␊ |
394 | ␉␉printf("Unable to locate _panic\n");␊ |
395 | ␉␉return;␊ |
396 | ␉}␊ |
397 | ␉␊ |
398 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
399 | ␉panicAddr -= (UInt32)kernelData;␊ |
400 | ␊ |
401 | ␊ |
402 | ␉␊ |
403 | ␉␊ |
404 | ␉␊ |
405 | ␉//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)␊ |
406 | ␉while( ␊ |
407 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
408 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
409 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
410 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
411 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
412 | ␉␉ )␊ |
413 | ␉{␊ |
414 | ␉␉patchLocation++;␊ |
415 | ␉}␊ |
416 | ␉patchLocation--;␊ |
417 | ␉␊ |
418 | ␉// Remove panic call, just in case the following patch routines fail␊ |
419 | ␉bytes[patchLocation + 0] = 0x90;␊ |
420 | ␉bytes[patchLocation + 1] = 0x90;␊ |
421 | ␉bytes[patchLocation + 2] = 0x90;␊ |
422 | ␉bytes[patchLocation + 3] = 0x90;␊ |
423 | ␉bytes[patchLocation + 4] = 0x90;␊ |
424 | ␉␊ |
425 | ␉␊ |
426 | ␉// Locate the jump call, so that 10 bytes can be reclamed.␊ |
427 | ␉// NOTE: This will *NOT* be located on pre 10.6.2 kernels␊ |
428 | ␉jumpLocation = patchLocation - 15;␊ |
429 | ␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
430 | ␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&␊ |
431 | ␉␉ (patchLocation - jumpLocation) < 0xF0)␊ |
432 | ␉{␊ |
433 | ␉␉jumpLocation--;␊ |
434 | ␉}␊ |
435 | ␉␊ |
436 | ␉// If found... AND we want to impersonate a specific cpumodel / family...␊ |
437 | ␉if(impersonateFamily &&␊ |
438 | ␉ impersonateModel &&␊ |
439 | ␉ ((patchLocation - jumpLocation) < 0xF0))␊ |
440 | ␉{␊ |
441 | ␉␉␊ |
442 | ␉␉bytes[jumpLocation] -= 10;␉␉// sizeof(movl␉$0x6b5a4cd2,0x00872eb4) = 10bytes␊ |
443 | ␉␉␊ |
444 | ␉␉/* ␊ |
445 | ␉␉ * Inpersonate the specified CPU FAMILY and CPU Model␊ |
446 | ␉␉ */␊ |
447 | ␊ |
448 | ␉␉// bytes[patchLocation - 17] = 0xC7;␉// already here... not needed to be done␊ |
449 | ␉␉// bytes[patchLocation - 16] = 0x05;␉// see above␊ |
450 | ␉␉UInt32 cpuid_cpufamily_addr =␉bytes[patchLocation - 15] << 0 |␊ |
451 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 14] << 8 |␊ |
452 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 16 |␊ |
453 | ␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 24;␊ |
454 | ␉␉␊ |
455 | ␉␉// NOTE: may change, determined based on cpuid_info struct␊ |
456 | ␉␉UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; ␊ |
457 | ␉␉␊ |
458 | ␉␉␊ |
459 | ␉␉// cpufamily = CPUFAMILY_INTEL_PENRYN␊ |
460 | ␉␉bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;␊ |
461 | ␉␉bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;␊ |
462 | ␉␉bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;␉␊ |
463 | ␉␉bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;␊ |
464 | ␉␉␊ |
465 | ␉␉// NOPS, just in case if the jmp call wasn't patched, we'll jump to a␊ |
466 | ␉␉// nop and continue with the rest of the patch␊ |
467 | ␉␉// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few␊ |
468 | ␉␉// from the above code (only cpuid_model needs to be set.␊ |
469 | ␉␉bytes[patchLocation - 7] = 0x90;␊ |
470 | ␉␉bytes[patchLocation - 6] = 0x90;␊ |
471 | ␉␉␊ |
472 | ␉␉bytes[patchLocation - 5] = 0xC7;␊ |
473 | ␉␉bytes[patchLocation - 4] = 0x05;␊ |
474 | ␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
475 | ␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
476 | ␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
477 | ␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
478 | ␉␉␊ |
479 | ␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
480 | ␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
481 | ␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
482 | ␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
483 | ␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
484 | ␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
485 | ␉␉␊ |
486 | ␉}␊ |
487 | ␉else if(impersonateFamily && impersonateModel)␊ |
488 | ␉{␊ |
489 | ␉␉// pre 10.6.2 kernel␊ |
490 | ␉␉// Locate the jump to directly *after* the panic call,␊ |
491 | ␉␉jumpLocation = patchLocation - 4;␊ |
492 | ␉␉while((bytes[jumpLocation - 1] != 0x77 ||␊ |
493 | ␉␉␉ bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&␊ |
494 | ␉␉␉ (patchLocation - jumpLocation) < 0x20)␊ |
495 | ␉␉{␊ |
496 | ␉␉␉jumpLocation--;␊ |
497 | ␉␉}␊ |
498 | ␉␉// NOTE above isn't needed (I was going to use it, but I'm not, so instead,␊ |
499 | ␉␉// I'll just leave it to verify the binary stucture.␊ |
500 | ␉␉␊ |
501 | ␉␉// NOTE: the cpumodel_familt data is not set in _cpuid_set_info␊ |
502 | ␉␉// so we don't need to set it here, I'll get set later based on the model␊ |
503 | ␉␉// we set now.␊ |
504 | ␉␉␊ |
505 | ␉␉if((patchLocation - jumpLocation) < 0x20)␊ |
506 | ␉␉{␊ |
507 | ␉␉␉UInt32 cpuid_model_addr =␉(bytes[patchLocation - 14] << 0 |␊ |
508 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 13] << 8 |␊ |
509 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 12] << 16 |␊ |
510 | ␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation - 11] << 24);␊ |
511 | ␉␉␉// Remove jump␊ |
512 | ␉␉␉bytes[patchLocation - 9] = 0x90;␉␉/// Was a jump if supported cpu␊ |
513 | ␉␉␉bytes[patchLocation - 8] = 0x90;␉␉// jumped past the panic call, we want to override the panic␊ |
514 | ␊ |
515 | ␉␉␉bytes[patchLocation - 7] = 0x90;␊ |
516 | ␉␉␉bytes[patchLocation - 6] = 0x90;␊ |
517 | ␉␉␉␊ |
518 | ␉␉␉bytes[patchLocation - 5] = 0xC7;␊ |
519 | ␉␉␉bytes[patchLocation - 4] = 0x05;␊ |
520 | ␉␉␉bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;␊ |
521 | ␉␉␉bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;␉␊ |
522 | ␉␉␉bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;␊ |
523 | ␉␉␉bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;␊ |
524 | ␉␉␉␊ |
525 | ␉␉␉// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes␊ |
526 | ␉␉␉// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.␊ |
527 | ␉␉␉bytes[patchLocation + 1] = impersonateModel;␉// cpuid_model␊ |
528 | ␉␉␉bytes[patchLocation + 2] = 0x01;␉// cpuid_extmodel␊ |
529 | ␉␉␉bytes[patchLocation + 3] = 0x00;␉// cpuid_extfamily␊ |
530 | ␉␉␉bytes[patchLocation + 4] = 0x02;␉// cpuid_stepping␊ |
531 | ␉␉␉␊ |
532 | ␉␉␉␊ |
533 | ␉␉␉␊ |
534 | ␉␉␉patchLocation = jumpLocation;␊ |
535 | ␉␉␉// We now have 14 bytes available for a patch␊ |
536 | ␉␉␉␊ |
537 | ␉␉}␊ |
538 | ␉␉else ␊ |
539 | ␉␉{␊ |
540 | ␉␉␉// Patching failed, using NOP replacement done initialy␊ |
541 | ␉␉}␊ |
542 | ␉}␊ |
543 | ␉else ␊ |
544 | ␉{␊ |
545 | ␉␉// Either We were unable to change the jump call due to the function's sctructure␊ |
546 | ␉␉// changing, or the user did not request a patch. As such, resort to just ␊ |
547 | ␉␉// removing the panic call (using NOP replacement above). Note that the␊ |
548 | ␉␉// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched␊ |
549 | ␉}␊ |
550 | }␊ |
551 | ␊ |
552 | ␊ |
553 | /**␊ |
554 | ** SleepEnabler.kext replacement (for those that need it)␊ |
555 | ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS␊ |
556 | **/␊ |
557 | void patch_pmCPUExitHaltToOff(void* kernelData)␊ |
558 | {␊ |
559 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
560 | ␊ |
561 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");␊ |
562 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;␊ |
563 | ␉␊ |
564 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
565 | ␉{␊ |
566 | ␉␉printf("Unable to locate _pmCPUExitHaltToOff\n");␊ |
567 | ␉␉return;␊ |
568 | ␉}␊ |
569 | ␉␊ |
570 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
571 | ␉␊ |
572 | ␉␊ |
573 | ␉␊ |
574 | ␉while(bytes[patchLocation - 1]␉!= 0xB8 ||␊ |
575 | ␉␉ bytes[patchLocation]␉␉!= 0x04 ||␉// KERN_INVALID_ARGUMENT (0x00000004)␊ |
576 | ␉␉ bytes[patchLocation + 1]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
577 | ␉␉ bytes[patchLocation + 2]␉!= 0x00 ||␉// KERN_INVALID_ARGUMENT␊ |
578 | ␉␉ bytes[patchLocation + 3]␉!= 0x00)␉// KERN_INVALID_ARGUMENT␊ |
579 | ␊ |
580 | ␉{␊ |
581 | ␉␉patchLocation++;␊ |
582 | ␉}␊ |
583 | ␉bytes[patchLocation] = 0x00;␉// KERN_SUCCESS;␊ |
584 | }␊ |
585 | ␊ |
586 | void patch_lapic_init(void* kernelData)␊ |
587 | {␊ |
588 | ␊ |
589 | ␉UInt8 panicIndex = 0;␊ |
590 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
591 | ␉␊ |
592 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");␊ |
593 | ␉UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; ␊ |
594 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
595 | ␉{␊ |
596 | ␉␉printf("Unable to locate %s\n", "_lapic_init");␊ |
597 | ␉␉return;␊ |
598 | ␉␉␊ |
599 | ␉}␊ |
600 | ␉␊ |
601 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
602 | ␉UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; ␊ |
603 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
604 | ␉{␊ |
605 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
606 | ␉␉return;␊ |
607 | ␉}␊ |
608 | ␉␊ |
609 | ␉patchLocation -= (UInt32)kernelData;␉// Remove offset␊ |
610 | ␉panicAddr -= (UInt32)kernelData;␉// Remove offset␊ |
611 | ␊ |
612 | ␉␊ |
613 | ␉␊ |
614 | ␉␊ |
615 | ␉// Locate the (panicIndex + 1) panic call␊ |
616 | ␉while(panicIndex < 3)␉// Find the third panic call␊ |
617 | ␉{␊ |
618 | ␉␉while( ␊ |
619 | ␉␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
620 | ␉␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
621 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
622 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
623 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
624 | ␉␉␉ )␊ |
625 | ␉␉{␊ |
626 | ␉␉␉patchLocation++;␊ |
627 | ␉␉}␊ |
628 | ␉␉patchLocation++;␊ |
629 | ␉␉panicIndex++;␊ |
630 | ␉}␊ |
631 | ␉patchLocation--;␉// Remove extra increment from the < 3 while loop␊ |
632 | ␉␊ |
633 | ␉bytes[--patchLocation] = 0x90;␉␊ |
634 | ␉bytes[++patchLocation] = 0x90;␊ |
635 | ␉bytes[++patchLocation] = 0x90;␊ |
636 | ␉bytes[++patchLocation] = 0x90;␊ |
637 | ␉bytes[++patchLocation] = 0x90;␊ |
638 | ␉␊ |
639 | ␉␊ |
640 | }␊ |
641 | ␊ |
642 | ␊ |
643 | void patch_commpage_stuff_routine(void* kernelData)␊ |
644 | {␊ |
645 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
646 | ␊ |
647 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");␊ |
648 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
649 | ␉{␊ |
650 | ␉␉printf("Unable to locate %s\n", "_commpage_stuff_routine");␊ |
651 | ␉␉return;␊ |
652 | ␉␉␊ |
653 | ␉}␊ |
654 | ␉␊ |
655 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
656 | ␊ |
657 | ␉␊ |
658 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
659 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
660 | ␉{␊ |
661 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
662 | ␉␉return;␊ |
663 | ␉}␊ |
664 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
665 | ␊ |
666 | ␉patchLocation -= (UInt32)kernelData;␊ |
667 | ␉panicAddr -= (UInt32)kernelData;␊ |
668 | ␉␊ |
669 | ␉while( ␊ |
670 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
671 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
672 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
673 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
674 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
675 | ␉␉ )␊ |
676 | ␉{␊ |
677 | ␉␉patchLocation++;␊ |
678 | ␉}␊ |
679 | ␉patchLocation--;␊ |
680 | ␉␊ |
681 | ␉// Replace panic with nops␊ |
682 | ␉bytes[patchLocation + 0] = 0x90;␊ |
683 | ␉bytes[patchLocation + 1] = 0x90;␊ |
684 | ␉bytes[patchLocation + 2] = 0x90;␊ |
685 | ␉bytes[patchLocation + 3] = 0x90;␊ |
686 | ␉bytes[patchLocation + 4] = 0x90;␊ |
687 | ␉␊ |
688 | ␉␊ |
689 | }␊ |
690 | ␊ |
691 | void patch_lapic_interrupt(void* kernelData)␊ |
692 | {␊ |
693 | ␉// NOTE: this is a hack untill I finish patch_lapic_configure␊ |
694 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
695 | ␉␊ |
696 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");␊ |
697 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
698 | ␉{␊ |
699 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt");␊ |
700 | ␉␉return;␊ |
701 | ␉␉␊ |
702 | ␉}␊ |
703 | ␉␊ |
704 | ␉UInt32 patchLocation = symbol->addr - textAddress + textSection; ␊ |
705 | ␉␊ |
706 | ␉␊ |
707 | ␉symbol = lookup_kernel_symbol("_panic");␊ |
708 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
709 | ␉{␊ |
710 | ␉␉printf("Unable to locate %s\n", "_panic");␊ |
711 | ␉␉return;␊ |
712 | ␉}␊ |
713 | ␉UInt32 panicAddr = symbol->addr - textAddress; ␊ |
714 | ␉␊ |
715 | ␉patchLocation -= (UInt32)kernelData;␊ |
716 | ␉panicAddr -= (UInt32)kernelData;␊ |
717 | ␉␊ |
718 | ␉while( ␊ |
719 | ␉␉ (bytes[patchLocation -1] != 0xE8) ||␊ |
720 | ␉␉ ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | ␊ |
721 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 1] << 8 | ␊ |
722 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 2] << 16 |␊ |
723 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉bytes[patchLocation + 3] << 24)))␊ |
724 | ␉␉ )␊ |
725 | ␉{␊ |
726 | ␉␉patchLocation++;␊ |
727 | ␉}␊ |
728 | ␉patchLocation--;␊ |
729 | ␉␊ |
730 | ␉// Replace panic with nops␊ |
731 | ␉bytes[patchLocation + 0] = 0x90;␊ |
732 | ␉bytes[patchLocation + 1] = 0x90;␊ |
733 | ␉bytes[patchLocation + 2] = 0x90;␊ |
734 | ␉bytes[patchLocation + 3] = 0x90;␊ |
735 | ␉bytes[patchLocation + 4] = 0x90;␊ |
736 | ␉␊ |
737 | ␉␊ |
738 | }␊ |
739 | ␊ |
740 | ␊ |
741 | void patch_lapic_configure(void* kernelData)␊ |
742 | {␊ |
743 | ␉UInt8* bytes = (UInt8*)kernelData;␊ |
744 | ␉␊ |
745 | ␉UInt32 patchLocation;␊ |
746 | ␉UInt32 lapicStart;␊ |
747 | ␉UInt32 lapicInterruptBase;␊ |
748 | ␉␊ |
749 | ␉kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");␊ |
750 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
751 | ␉{␊ |
752 | ␉␉printf("Unable to locate %s\n", "_lapic_configure");␊ |
753 | ␉␉return;␊ |
754 | ␉}␊ |
755 | ␉patchLocation = symbol->addr - textAddress + textSection; ␊ |
756 | ␉␊ |
757 | ␉symbol = lookup_kernel_symbol("_lapic_start");␊ |
758 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
759 | ␉{␊ |
760 | ␉␉printf("Unable to locate %s\n", "_lapic_start");␊ |
761 | ␉␉return;␊ |
762 | ␉}␊ |
763 | ␉lapicStart = symbol->addr; ␊ |
764 | ␊ |
765 | ␊ |
766 | ␉symbol = lookup_kernel_symbol("_lapic_interrupt_base");␊ |
767 | ␉if(symbol == 0 || symbol->addr == 0)␊ |
768 | ␉{␊ |
769 | ␉␉printf("Unable to locate %s\n", "_lapic_interrupt_base");␊ |
770 | ␉␉return;␊ |
771 | ␉}␊ |
772 | ␉lapicInterruptBase = symbol->addr;␊ |
773 | ␉patchLocation -= (UInt32)kernelData;␊ |
774 | ␉lapicStart -= (UInt32)kernelData;␊ |
775 | ␉lapicInterruptBase -= (UInt32)kernelData;␊ |
776 | ␉␊ |
777 | ␉␊ |
778 | ␉// Looking for the following:␊ |
779 | ␉//movl _lapic_start,%e_x␊ |
780 | ␉//addl $0x00000320,%e_x␊ |
781 | ␉// 8b 15 __ __ __ __ 81 c2 20 03 00 00␊ |
782 | ␉while( ␊ |
783 | ␉␉ (bytes[patchLocation - 2] != 0x8b) ||␊ |
784 | ␉␉ //bytes[patchLocation -1] != 0x15) ||␉// Register, we don't care what it is␊ |
785 | ␉␉ ( lapicStart != (UInt32)(␊ |
786 | ␉␉␉␉␉␉␉␉␉(bytes[patchLocation + 0] << 0 | ␊ |
787 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 1] << 8 | ␊ |
788 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 2] << 16 |␊ |
789 | ␉␉␉␉␉␉␉␉␉ bytes[patchLocation + 3] << 24␊ |
790 | ␉␉␉␉␉␉␉␉␉)␊ |
791 | ␉␉␉␉␉␉␉␉ )␊ |
792 | ␉␉ ) || ␊ |
793 | ␉␉ (bytes[patchLocation + 4 ] != 0x81) ||␊ |
794 | ␉␉ //(bytes[patchLocation + 5 ] != 0Cx2) ||␉// register␊ |
795 | ␉␉ (bytes[patchLocation + 6 ] != 0x20) ||␊ |
796 | ␉␉ (bytes[patchLocation + 7 ] != 0x03) ||␊ |
797 | ␉␉ (bytes[patchLocation + 8 ] != 0x00) ||␊ |
798 | ␉␉ (bytes[patchLocation + 9] != 0x00)␊ |
799 | ␊ |
800 | ␉␉ )␊ |
801 | ␉{␊ |
802 | ␉␉patchLocation++;␊ |
803 | ␉}␊ |
804 | ␉patchLocation-=2;␊ |
805 | ␊ |
806 | ␉// NOTE: this is currently hardcoded, change it to be more resilient to changes␊ |
807 | ␉// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.␊ |
808 | ␉␊ |
809 | ␉// 8b 15 __ __ __ __ -> movl␉␉ _lapic_start,%edx (NOTE: this should already be here)␊ |
810 | ␉/*␊ |
811 | ␉bytes[patchLocation++] = 0x8B;␊ |
812 | ␉bytes[patchLocation++] = 0x15;␊ |
813 | ␉bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;␊ |
814 | ␉bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;␊ |
815 | ␉bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;␊ |
816 | ␉bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;␊ |
817 | ␉*/␊ |
818 | ␉patchLocation += 6;␊ |
819 | ␉␊ |
820 | ␉// 81 c2 60 03 00 00 -> addl␉␉ $0x00000320,%edx␊ |
821 | ␉/*␊ |
822 | ␉bytes[patchLocation++] = 0x81;␊ |
823 | ␉bytes[patchLocation++] = 0xC2;␊ |
824 | ␉*/␊ |
825 | ␉patchLocation += 2;␊ |
826 | ␉bytes[patchLocation++] = 0x60;␊ |
827 | ␉/*␊ |
828 | ␉bytes[patchLocation++];// = 0x03;␊ |
829 | ␉bytes[patchLocation++];// = 0x00;␊ |
830 | ␉bytes[patchLocation++];// = 0x00;␊ |
831 | ␉*/␊ |
832 | ␉ patchLocation += 3;␊ |
833 | ␊ |
834 | ␉// c7 02 00 04 00 00 -> movl␉␉ $0x00000400,(%edx)␊ |
835 | ␉bytes[patchLocation++] = 0xC7;␊ |
836 | ␉bytes[patchLocation++] = 0x02;␊ |
837 | ␉bytes[patchLocation++] = 0x00;␊ |
838 | ␉bytes[patchLocation++] = 0x04;␊ |
839 | ␉bytes[patchLocation++] = 0x00;␊ |
840 | ␉bytes[patchLocation++] = 0x00;␊ |
841 | ␉␊ |
842 | ␉// 83 ea 40 -> subl␉␉ $0x40,edx␊ |
843 | ␉bytes[patchLocation++] = 0x83;␊ |
844 | ␉bytes[patchLocation++] = 0xEA;␊ |
845 | ␉bytes[patchLocation++] = 0x40;␊ |
846 | ␊ |
847 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
848 | ␉bytes[patchLocation++] = 0xA1;␊ |
849 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
850 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
851 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
852 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
853 | ␊ |
854 | ␉// 83 c0 0e -> addl␉␉ $0x0e,%eax␊ |
855 | ␉bytes[patchLocation++] = 0x83;␊ |
856 | ␉bytes[patchLocation++] = 0xC0;␊ |
857 | ␉bytes[patchLocation++] = 0x0E;␊ |
858 | ␊ |
859 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
860 | ␉bytes[patchLocation++] = 0x89;␊ |
861 | ␉bytes[patchLocation++] = 0x02;␊ |
862 | ␉␊ |
863 | ␉// 81c230030000␉␉ addl␉␉ $0x00000330,%edx␊ |
864 | ␉bytes[patchLocation++] = 0x81;␊ |
865 | ␉bytes[patchLocation++] = 0xC2;␊ |
866 | ␉bytes[patchLocation++] = 0x30;␊ |
867 | ␉bytes[patchLocation++] = 0x03;␊ |
868 | ␉bytes[patchLocation++] = 0x00;␊ |
869 | ␉bytes[patchLocation++] = 0x00;␊ |
870 | ␉␊ |
871 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
872 | ␉bytes[patchLocation++] = 0xA1;␊ |
873 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
874 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
875 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
876 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
877 | ␉␊ |
878 | ␉// 83 c0 0f -> addl␉␉ $0x0f,%eax␊ |
879 | ␉bytes[patchLocation++] = 0x83;␊ |
880 | ␉bytes[patchLocation++] = 0xC0;␊ |
881 | ␉bytes[patchLocation++] = 0x0F;␊ |
882 | ␉␊ |
883 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
884 | ␉bytes[patchLocation++] = 0x89;␊ |
885 | ␉bytes[patchLocation++] = 0x02;␊ |
886 | ␉␊ |
887 | ␉// 83 ea 10 -> subl␉␉ $0x10,edx␊ |
888 | ␉bytes[patchLocation++] = 0x83;␊ |
889 | ␉bytes[patchLocation++] = 0xEA;␊ |
890 | ␉bytes[patchLocation++] = 0x10;␊ |
891 | ␊ |
892 | ␉// a1 __ __ __ __ -> movl␉␉ _lapic_interrupt_base,%eax␊ |
893 | ␉bytes[patchLocation++] = 0xA1;␊ |
894 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;␊ |
895 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;␊ |
896 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;␊ |
897 | ␉bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;␊ |
898 | ␉␊ |
899 | ␉// 83 c0 0c -> addl␉␉ $0x0c,%eax␊ |
900 | ␉bytes[patchLocation++] = 0x83;␊ |
901 | ␉bytes[patchLocation++] = 0xC0;␊ |
902 | ␉bytes[patchLocation++] = 0x0C;␊ |
903 | ␊ |
904 | ␉// 89 02 -> movl␉␉ %eax,(%edx)␊ |
905 | ␉bytes[patchLocation++] = 0x89;␊ |
906 | ␉bytes[patchLocation++] = 0x02;␊ |
907 | ␊ |
908 | ␉// Replace remaining with nops␊ |
909 | ␊ |
910 | ␊ |
911 | ␉bytes[patchLocation++] = 0x90;␊ |
912 | ␉bytes[patchLocation++] = 0x90;␊ |
913 | ␉bytes[patchLocation++] = 0x90;␊ |
914 | ␉bytes[patchLocation++] = 0x90;␊ |
915 | ␉//␉bytes[patchLocation++] = 0x90; // double check the lenght of the patch...␊ |
916 | ␉//␉bytes[patchLocation++] = 0x90;␊ |
917 | }␊ |
918 |