Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c

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

Archive Download this file

Revision: 482