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 "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 = 0; //Azi:warning
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
289return handle_symtable((UInt32)kernelData, symtableData, &symbol_handler,
290determineKernelArchitecture(kernelData) == KERNEL_64);
291}
292
293long long symbol_handler(char* symbolName, long long addr, char is64)
294{
295// Locate the symbol in the list, if it exists, update it's address
296kernSymbols_t *symbol = lookup_kernel_symbol(symbolName);
297
298
299if(symbol)
300{
301symbol->addr = addr;
302}
303return 0xFFFFFFFF; // fixme
304}
305
306
307/**
308 ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it
309 ** Or replace it so that the cpuid is set to a valid value.
310 **/
311void patch_cpuid_set_info_all(void* kernelData)
312{
313switch(Platform.CPU.Model)
314{
315case CPUID_MODEL_ATOM:
316patch_cpuid_set_info(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN);
317break;
318
319default:
320patch_cpuid_set_info(kernelData, 0, 0);
321break;
322}
323}
324
325void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel)
326{
327UInt8* bytes = (UInt8*)kernelData;
328
329kernSymbols_t *symbol = lookup_kernel_symbol("_cpuid_set_info");
330UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0; //(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection);
331
332UInt32 jumpLocation = 0;
333
334
335if(symbol == 0 || symbol->addr == 0)
336{
337printf("Unable to locate _cpuid_set_info\n");
338return;
339
340}
341
342symbol = lookup_kernel_symbol("_panic");
343UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0; //kernelSymbolAddresses[SYMBOL_PANIC] - textAddress;
344if(symbol == 0 || symbol->addr == 0)
345{
346printf("Unable to locate _panic\n");
347return;
348}
349
350patchLocation -= (UInt32)kernelData;// Remove offset
351panicAddr -= (UInt32)kernelData;
352
353
354
355
356
357//TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached)
358while(
359 (bytes[patchLocation -1] != 0xE8) ||
360 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
361bytes[patchLocation + 1] << 8 |
362bytes[patchLocation + 2] << 16 |
363bytes[patchLocation + 3] << 24)))
364 )
365{
366patchLocation++;
367}
368patchLocation--;
369
370// Remove panic call, just in case the following patch routines fail
371bytes[patchLocation + 0] = 0x90;
372bytes[patchLocation + 1] = 0x90;
373bytes[patchLocation + 2] = 0x90;
374bytes[patchLocation + 3] = 0x90;
375bytes[patchLocation + 4] = 0x90;
376
377
378// Locate the jump call, so that 10 bytes can be reclamed.
379// NOTE: This will *NOT* be located on pre 10.6.2 kernels
380jumpLocation = patchLocation - 15;
381while((bytes[jumpLocation - 1] != 0x77 ||
382 bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) &&
383 (patchLocation - jumpLocation) < 0xF0)
384{
385jumpLocation--;
386}
387
388// If found... AND we want to impersonate a specific cpumodel / family...
389if(impersonateFamily &&
390 impersonateModel &&
391 ((patchLocation - jumpLocation) < 0xF0))
392{
393
394bytes[jumpLocation] -= 10;// sizeof(movl$0x6b5a4cd2,0x00872eb4) = 10bytes
395
396/*
397 * Inpersonate the specified CPU FAMILY and CPU Model
398 */
399
400// bytes[patchLocation - 17] = 0xC7;// already here... not needed to be done
401// bytes[patchLocation - 16] = 0x05;// see above
402UInt32 cpuid_cpufamily_addr =bytes[patchLocation - 15] << 0 |
403bytes[patchLocation - 14] << 8 |
404bytes[patchLocation - 13] << 16 |
405bytes[patchLocation - 12] << 24;
406
407// NOTE: may change, determined based on cpuid_info struct
408UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299;
409
410
411// cpufamily = CPUFAMILY_INTEL_PENRYN
412bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0;
413bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8;
414bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16;
415bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24;
416
417// NOPS, just in case if the jmp call wasn't patched, we'll jump to a
418// nop and continue with the rest of the patch
419// Yay two free bytes :), 10 more can be reclamed if needed, as well as a few
420// from the above code (only cpuid_model needs to be set.
421bytes[patchLocation - 7] = 0x90;
422bytes[patchLocation - 6] = 0x90;
423
424bytes[patchLocation - 5] = 0xC7;
425bytes[patchLocation - 4] = 0x05;
426bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
427bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
428bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
429bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
430
431// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
432// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
433bytes[patchLocation + 1] = impersonateModel;// cpuid_model
434bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
435bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
436bytes[patchLocation + 4] = 0x02;// cpuid_stepping
437
438}
439else if(impersonateFamily && impersonateModel)
440{
441// pre 10.6.2 kernel
442// Locate the jump to directly *after* the panic call,
443jumpLocation = patchLocation - 4;
444while((bytes[jumpLocation - 1] != 0x77 ||
445 bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) &&
446 (patchLocation - jumpLocation) < 0x20)
447{
448jumpLocation--;
449}
450// NOTE above isn't needed (I was going to use it, but I'm not, so instead,
451// I'll just leave it to verify the binary stucture.
452
453// NOTE: the cpumodel_familt data is not set in _cpuid_set_info
454// so we don't need to set it here, I'll get set later based on the model
455// we set now.
456
457if((patchLocation - jumpLocation) < 0x20)
458{
459UInt32 cpuid_model_addr =(bytes[patchLocation - 14] << 0 |
460bytes[patchLocation - 13] << 8 |
461bytes[patchLocation - 12] << 16 |
462bytes[patchLocation - 11] << 24);
463// Remove jump
464bytes[patchLocation - 9] = 0x90;/// Was a jump if supported cpu
465bytes[patchLocation - 8] = 0x90;// jumped past the panic call, we want to override the panic
466
467bytes[patchLocation - 7] = 0x90;
468bytes[patchLocation - 6] = 0x90;
469
470bytes[patchLocation - 5] = 0xC7;
471bytes[patchLocation - 4] = 0x05;
472bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0;
473bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8;
474bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16;
475bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24;
476
477// Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes
478// so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed.
479bytes[patchLocation + 1] = impersonateModel;// cpuid_model
480bytes[patchLocation + 2] = 0x01;// cpuid_extmodel
481bytes[patchLocation + 3] = 0x00;// cpuid_extfamily
482bytes[patchLocation + 4] = 0x02;// cpuid_stepping
483
484
485
486patchLocation = jumpLocation;
487// We now have 14 bytes available for a patch
488
489}
490else
491{
492// Patching failed, using NOP replacement done initialy
493}
494}
495else
496{
497// Either We were unable to change the jump call due to the function's sctructure
498// changing, or the user did not request a patch. As such, resort to just
499// removing the panic call (using NOP replacement above). Note that the
500// IntelCPUPM kext may still panic due to the cpu's Model ID not being patched
501}
502}
503
504
505/**
506 ** SleepEnabler.kext replacement (for those that need it)
507 ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS
508 **/
509void patch_pmCPUExitHaltToOff(void* kernelData)
510{
511UInt8* bytes = (UInt8*)kernelData;
512
513kernSymbols_t *symbol = lookup_kernel_symbol("_PmCpuExitHaltToOff");
514UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;
515
516if(symbol == 0 || symbol->addr == 0)
517{
518printf("Unable to locate _pmCPUExitHaltToOff\n");
519return;
520}
521
522patchLocation -= (UInt32)kernelData;// Remove offset
523
524
525
526while(bytes[patchLocation - 1]!= 0xB8 ||
527 bytes[patchLocation]!= 0x04 ||// KERN_INVALID_ARGUMENT (0x00000004)
528 bytes[patchLocation + 1]!= 0x00 ||// KERN_INVALID_ARGUMENT
529 bytes[patchLocation + 2]!= 0x00 ||// KERN_INVALID_ARGUMENT
530 bytes[patchLocation + 3]!= 0x00)// KERN_INVALID_ARGUMENT
531
532{
533patchLocation++;
534}
535bytes[patchLocation] = 0x00;// KERN_SUCCESS;
536}
537
538void patch_lapic_init(void* kernelData)
539{
540
541UInt8 panicIndex = 0;
542UInt8* bytes = (UInt8*)kernelData;
543
544kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_init");
545UInt32 patchLocation = symbol ? symbol->addr - textAddress + textSection: 0;
546if(symbol == 0 || symbol->addr == 0)
547{
548printf("Unable to locate %s\n", "_lapic_init");
549return;
550
551}
552
553symbol = lookup_kernel_symbol("_panic");
554UInt32 panicAddr = symbol ? symbol->addr - textAddress: 0;
555if(symbol == 0 || symbol->addr == 0)
556{
557printf("Unable to locate %s\n", "_panic");
558return;
559}
560
561patchLocation -= (UInt32)kernelData;// Remove offset
562panicAddr -= (UInt32)kernelData;// Remove offset
563
564
565
566
567// Locate the (panicIndex + 1) panic call
568while(panicIndex < 3)// Find the third panic call
569{
570while(
571 (bytes[patchLocation -1] != 0xE8) ||
572 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
573bytes[patchLocation + 1] << 8 |
574bytes[patchLocation + 2] << 16 |
575bytes[patchLocation + 3] << 24)))
576 )
577{
578patchLocation++;
579}
580patchLocation++;
581panicIndex++;
582}
583patchLocation--;// Remove extra increment from the < 3 while loop
584
585bytes[--patchLocation] = 0x90;
586bytes[++patchLocation] = 0x90;
587bytes[++patchLocation] = 0x90;
588bytes[++patchLocation] = 0x90;
589bytes[++patchLocation] = 0x90;
590
591
592}
593
594
595void patch_commpage_stuff_routine(void* kernelData)
596{
597UInt8* bytes = (UInt8*)kernelData;
598
599kernSymbols_t *symbol = lookup_kernel_symbol("_commpage_stuff_routine");
600if(symbol == 0 || symbol->addr == 0)
601{
602printf("Unable to locate %s\n", "_commpage_stuff_routine");
603return;
604
605}
606
607UInt32 patchLocation = symbol->addr - textAddress + textSection;
608
609
610symbol = lookup_kernel_symbol("_panic");
611if(symbol == 0 || symbol->addr == 0)
612{
613printf("Unable to locate %s\n", "_panic");
614return;
615}
616UInt32 panicAddr = symbol->addr - textAddress;
617
618patchLocation -= (UInt32)kernelData;
619panicAddr -= (UInt32)kernelData;
620
621while(
622 (bytes[patchLocation -1] != 0xE8) ||
623 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
624bytes[patchLocation + 1] << 8 |
625bytes[patchLocation + 2] << 16 |
626bytes[patchLocation + 3] << 24)))
627 )
628{
629patchLocation++;
630}
631patchLocation--;
632
633// Replace panic with nops
634bytes[patchLocation + 0] = 0x90;
635bytes[patchLocation + 1] = 0x90;
636bytes[patchLocation + 2] = 0x90;
637bytes[patchLocation + 3] = 0x90;
638bytes[patchLocation + 4] = 0x90;
639
640
641}
642
643void patch_lapic_interrupt(void* kernelData)
644{
645// NOTE: this is a hack untill I finish patch_lapic_configure
646UInt8* bytes = (UInt8*)kernelData;
647
648kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_interrupt");
649if(symbol == 0 || symbol->addr == 0)
650{
651printf("Unable to locate %s\n", "_lapic_interrupt");
652return;
653
654}
655
656UInt32 patchLocation = symbol->addr - textAddress + textSection;
657
658
659symbol = lookup_kernel_symbol("_panic");
660if(symbol == 0 || symbol->addr == 0)
661{
662printf("Unable to locate %s\n", "_panic");
663return;
664}
665UInt32 panicAddr = symbol->addr - textAddress;
666
667patchLocation -= (UInt32)kernelData;
668panicAddr -= (UInt32)kernelData;
669
670while(
671 (bytes[patchLocation -1] != 0xE8) ||
672 ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 |
673bytes[patchLocation + 1] << 8 |
674bytes[patchLocation + 2] << 16 |
675bytes[patchLocation + 3] << 24)))
676 )
677{
678patchLocation++;
679}
680patchLocation--;
681
682// Replace panic with nops
683bytes[patchLocation + 0] = 0x90;
684bytes[patchLocation + 1] = 0x90;
685bytes[patchLocation + 2] = 0x90;
686bytes[patchLocation + 3] = 0x90;
687bytes[patchLocation + 4] = 0x90;
688
689
690}
691
692
693void patch_lapic_configure(void* kernelData)
694{
695UInt8* bytes = (UInt8*)kernelData;
696
697UInt32 patchLocation;
698UInt32 lapicStart;
699UInt32 lapicInterruptBase;
700
701kernSymbols_t *symbol = lookup_kernel_symbol("_lapic_configure");
702if(symbol == 0 || symbol->addr == 0)
703{
704printf("Unable to locate %s\n", "_lapic_configure");
705return;
706}
707patchLocation = symbol->addr - textAddress + textSection;
708
709symbol = lookup_kernel_symbol("_lapic_start");
710if(symbol == 0 || symbol->addr == 0)
711{
712printf("Unable to locate %s\n", "_lapic_start");
713return;
714}
715lapicStart = symbol->addr;
716
717
718symbol = lookup_kernel_symbol("_lapic_interrupt_base");
719if(symbol == 0 || symbol->addr == 0)
720{
721printf("Unable to locate %s\n", "_lapic_interrupt_base");
722return;
723}
724lapicInterruptBase = symbol->addr;
725patchLocation -= (UInt32)kernelData;
726lapicStart -= (UInt32)kernelData;
727lapicInterruptBase -= (UInt32)kernelData;
728
729
730// Looking for the following:
731//movl _lapic_start,%e_x
732//addl $0x00000320,%e_x
733// 8b 15 __ __ __ __ 81 c2 20 03 00 00
734while(
735 (bytes[patchLocation - 2] != 0x8b) ||
736 //bytes[patchLocation -1] != 0x15) ||// Register, we don't care what it is
737 ( lapicStart != (UInt32)(
738(bytes[patchLocation + 0] << 0 |
739 bytes[patchLocation + 1] << 8 |
740 bytes[patchLocation + 2] << 16 |
741 bytes[patchLocation + 3] << 24
742)
743 )
744 ) ||
745 (bytes[patchLocation + 4 ] != 0x81) ||
746 //(bytes[patchLocation + 5 ] != 0Cx2) ||// register
747 (bytes[patchLocation + 6 ] != 0x20) ||
748 (bytes[patchLocation + 7 ] != 0x03) ||
749 (bytes[patchLocation + 8 ] != 0x00) ||
750 (bytes[patchLocation + 9] != 0x00)
751
752 )
753{
754patchLocation++;
755}
756patchLocation-=2;
757
758// NOTE: this is currently hardcoded, change it to be more resilient to changes
759// At a minimum, I should have this do a cheksup first and if not matching, remove the panic instead.
760
761// 8b 15 __ __ __ __ -> movl _lapic_start,%edx (NOTE: this should already be here)
762/*
763bytes[patchLocation++] = 0x8B;
764bytes[patchLocation++] = 0x15;
765bytes[patchLocation++] = (lapicStart & 0x000000FF) >> 0;
766bytes[patchLocation++] = (lapicStart & 0x0000FF00) >> 8;
767bytes[patchLocation++] = (lapicStart & 0x00FF0000) >> 16;
768bytes[patchLocation++] = (lapicStart & 0xFF000000) >> 24;
769*/
770patchLocation += 6;
771
772// 81 c2 60 03 00 00 -> addl $0x00000320,%edx
773/*
774bytes[patchLocation++] = 0x81;
775bytes[patchLocation++] = 0xC2;
776*/
777patchLocation += 2;
778bytes[patchLocation++] = 0x60;
779/*
780bytes[patchLocation++];// = 0x03;
781bytes[patchLocation++];// = 0x00;
782bytes[patchLocation++];// = 0x00;
783*/
784 patchLocation += 3;
785
786// c7 02 00 04 00 00 -> movl $0x00000400,(%edx)
787bytes[patchLocation++] = 0xC7;
788bytes[patchLocation++] = 0x02;
789bytes[patchLocation++] = 0x00;
790bytes[patchLocation++] = 0x04;
791bytes[patchLocation++] = 0x00;
792bytes[patchLocation++] = 0x00;
793
794// 83 ea 40 -> subl $0x40,edx
795bytes[patchLocation++] = 0x83;
796bytes[patchLocation++] = 0xEA;
797bytes[patchLocation++] = 0x40;
798
799// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
800bytes[patchLocation++] = 0xA1;
801bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
802bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
803bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
804bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
805
806// 83 c0 0e -> addl $0x0e,%eax
807bytes[patchLocation++] = 0x83;
808bytes[patchLocation++] = 0xC0;
809bytes[patchLocation++] = 0x0E;
810
811// 89 02 -> movl %eax,(%edx)
812bytes[patchLocation++] = 0x89;
813bytes[patchLocation++] = 0x02;
814
815// 81c230030000 addl $0x00000330,%edx
816bytes[patchLocation++] = 0x81;
817bytes[patchLocation++] = 0xC2;
818bytes[patchLocation++] = 0x30;
819bytes[patchLocation++] = 0x03;
820bytes[patchLocation++] = 0x00;
821bytes[patchLocation++] = 0x00;
822
823// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
824bytes[patchLocation++] = 0xA1;
825bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
826bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
827bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
828bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
829
830// 83 c0 0f -> addl $0x0f,%eax
831bytes[patchLocation++] = 0x83;
832bytes[patchLocation++] = 0xC0;
833bytes[patchLocation++] = 0x0F;
834
835// 89 02 -> movl %eax,(%edx)
836bytes[patchLocation++] = 0x89;
837bytes[patchLocation++] = 0x02;
838
839// 83 ea 10 -> subl $0x10,edx
840bytes[patchLocation++] = 0x83;
841bytes[patchLocation++] = 0xEA;
842bytes[patchLocation++] = 0x10;
843
844// a1 __ __ __ __ -> movl _lapic_interrupt_base,%eax
845bytes[patchLocation++] = 0xA1;
846bytes[patchLocation++] = (lapicInterruptBase & 0x000000FF) >> 0;
847bytes[patchLocation++] = (lapicInterruptBase & 0x0000FF00) >> 8;
848bytes[patchLocation++] = (lapicInterruptBase & 0x00FF0000) >> 16;
849bytes[patchLocation++] = (lapicInterruptBase & 0xFF000000) >> 24;
850
851// 83 c0 0c -> addl $0x0c,%eax
852bytes[patchLocation++] = 0x83;
853bytes[patchLocation++] = 0xC0;
854bytes[patchLocation++] = 0x0C;
855
856// 89 02 -> movl %eax,(%edx)
857bytes[patchLocation++] = 0x89;
858bytes[patchLocation++] = 0x02;
859
860// Replace remaining with nops
861
862
863bytes[patchLocation++] = 0x90;
864bytes[patchLocation++] = 0x90;
865bytes[patchLocation++] = 0x90;
866bytes[patchLocation++] = 0x90;
867//bytes[patchLocation++] = 0x90; // double check the lenght of the patch...
868//bytes[patchLocation++] = 0x90;
869}
870

Archive Download this file

Revision: 486