Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/modules/KernelPatcher/kernel_patcher.c

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

Archive Download this file

Revision: 495