Index: branches/meklort/i386/boot2/kernel_patcher.c =================================================================== --- branches/meklort/i386/boot2/kernel_patcher.c (revision 440) +++ branches/meklort/i386/boot2/kernel_patcher.c (revision 441) @@ -1,544 +0,0 @@ -/* - * Copyright (c) 2009 Evan Lojewski. All rights reserved. - * - */ - -#include "libsaio.h" -#include "kernel_patcher.h" -#include "platform.h" - -extern PlatformInfo_t Platform; - - -#define SYMBOL_CPUID_SET_INFO 0 -#define SYMBOL_PANIC 1 -#define SYMBOL_PMCPUEXITHALTTOOFF 2 -#define SYMBOL_LAPIC_INIT 3 -#define SYMBOL_COMMPAGE_STUFF_ROUTINE 4 -#define NUM_SYMBOLS 5 - -#define SYMBOL_CPUID_SET_INFO_STRING "_cpuid_set_info" -#define SYMBOL_PANIC_STRING "_panic" -#define SYMBOL_PMCPUEXITHALTTOOFF_STRING "_pmCPUExitHaltToOff" -#define SYMBOL_LAPIC_INIT_STRING "_lapic_init" -#define SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING "_commpage_stuff_routine" - -char* kernelSymbols[NUM_SYMBOLS] = { - SYMBOL_CPUID_SET_INFO_STRING, - SYMBOL_PANIC_STRING, - SYMBOL_PMCPUEXITHALTTOOFF_STRING, - SYMBOL_LAPIC_INIT_STRING, - SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING -}; - -UInt32 kernelSymbolAddresses[NUM_SYMBOLS] = { - 0, - 0, - 0, - 0, - 0 -}; - - -UInt32 textSection = 0; -UInt32 textAddress = 0; - - -void patch_kernel(void* kernelData) -{ - switch (locate_symbols((void*)kernelData)) { - case KERNEL_32: - patch_kernel_32((void*)kernelData); - break; - - case KERNEL_64: - default: - patch_kernel_64((void*)kernelData); - break; - } -} - -// patches a 64bit kernel. -void patch_kernel_64(void* kernelData) -{ - // At the moment, the kernel patching code fails when used - // in 64bit mode, so we don't patch it. This is due to 32bit vs 64bit - // pointers as well as changes in structure sizes - printf("Unable to patch 64bit kernel. Please use arch=i386.\n"); -} - - -/** - ** patch_kernel_32 - ** patches kernel based on cpu info determined earlier in the boot process. - ** It the machine is vmware, remove the artificial lapic panic - ** If the CPU is not supported, remove the cpuid_set_info panic - ** If the CPU is and Intel Atom, inject the penryn cpuid info. - **/ -void patch_kernel_32(void* kernelData) -{ - // Remove panic in commpage - patch_commpage_stuff_routine(kernelData); - - //patch_pmCPUExitHaltToOff(kernelData); // Not working as intended, disabled for now - - // if(vmware_detected) - { - patch_lapic_init(kernelData); - } - - switch(Platform.CPU.Model) - { - // Known good CPU's, no reason to patch kernel - case 13: - case CPUID_MODEL_YONAH: - case CPUID_MODEL_MEROM: - case CPUID_MODEL_PENRYN: - case CPUID_MODEL_NEHALEM: - case CPUID_MODEL_FIELDS: - case CPUID_MODEL_DALES: - case CPUID_MODEL_NEHALEM_EX: - break; - - // Known unsuported CPU's - case CPUID_MODEL_ATOM: - // TODO: Impersonate CPU based on user selection - patch_cpuid_set_info(kernelData, CPUFAMILY_INTEL_PENRYN, CPUID_MODEL_PENRYN); // Impersonate Penryn CPU - break; - - // Unknown CPU's - default: - // TODO: Impersonate CPU based on user selection - patch_cpuid_set_info(kernelData, 0, 0); // Remove Panic Call - - break; - } -} - - -/** - ** This functions located the kernelSymbols[i] symbols in the mach-o header. - ** as well as determines the start of the __TEXT segment and __TEXT,__text sections - **/ -int locate_symbols(void* kernelData) -{ - UInt16 symbolIndexes[NUM_SYMBOLS]; - - struct load_command *loadCommand; - struct symtab_command *symtableData; - struct nlist *symbolEntry; - - char* symbolString; - - UInt32 kernelIndex = 0; - kernelIndex += sizeof(struct mach_header); - - if(((struct mach_header*)kernelData)->magic != MH_MAGIC) return KERNEL_64; - - - //printf("%d load commands beginning at 0x%X\n", (unsigned int)header->ncmds, (unsigned int)kernelIndex); - //printf("Commands take up %d bytes\n", header->sizeofcmds); - - - int cmd = 0; - while(cmd < ((struct mach_header*)kernelData)->ncmds) // TODO: for loop instead - { - cmd++; - - loadCommand = kernelData + kernelIndex; - - UInt cmdSize = loadCommand->cmdsize; - - - // Locate start of _panic and _cpuid_set_info in the symbol tabe. - // Load commands should be anded with 0x7FFFFFFF to ignore the LC_REQ_DYLD flag - if((loadCommand->cmd & 0x7FFFFFFF) == LC_SYMTAB) // We only care about the symtab segment - { - //printf("Located symtable, length is 0x%X, 0x%X\n", (unsigned int)loadCommand->cmdsize, (unsigned int)sizeof(symtableData)); - - symtableData = kernelData + kernelIndex; - kernelIndex += sizeof(struct symtab_command); - - cmdSize -= sizeof(struct symtab_command); - - // Loop through symbol table untill all of the symbols have been found - - symbolString = kernelData + symtableData->stroff; - - - UInt16 symbolIndex = 0; - UInt8 numSymbolsFound = 0; - - while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS) // TODO: for loop - { - int i = 0; - while(i < NUM_SYMBOLS) - { - if(strcmp(symbolString, kernelSymbols[i]) == 0) - { - symbolIndexes[i] = symbolIndex; - numSymbolsFound++; - } - i++; - - } - symbolString += strlen(symbolString) + 1; - symbolIndex++; - } - - // loop again - symbolIndex = 0; - numSymbolsFound = 0; - while(symbolIndex < symtableData->nsyms && numSymbolsFound < NUM_SYMBOLS) // TODO: for loop - { - - symbolEntry = kernelData + symtableData->symoff + (symbolIndex * sizeof(struct nlist)); - - int i = 0; - while(i < NUM_SYMBOLS) - { - if(symbolIndex == (symbolIndexes[i] - 4)) - { - kernelSymbolAddresses[i] = (UInt32)symbolEntry->n_value; - numSymbolsFound++; - } - i++; - - } - - symbolIndex ++; - } - // Load commands should be anded with 0x7FFFFFFF to ignore the LC_REQ_DYLD flag - } else if((loadCommand->cmd & 0x7FFFFFFF) == LC_SEGMENT) // We only care about the __TEXT segment, any other load command can be ignored - { - - struct segment_command *segCommand; - - segCommand = kernelData + kernelIndex; - - //printf("Segment name is %s\n", segCommand->segname); - - if(strcmp("__TEXT", segCommand->segname) == 0) - { - UInt32 sectionIndex; - - sectionIndex = sizeof(struct segment_command); - - struct section *sect; - - while(sectionIndex < segCommand->cmdsize) - { - sect = kernelData + kernelIndex + sectionIndex; - - sectionIndex += sizeof(struct section); - - - if(strcmp("__text", sect->sectname) == 0) - { - // __TEXT,__text found, save the offset and address for when looking for the calls. - textSection = sect->offset; - textAddress = sect->addr; - break; - } - } - } - - - kernelIndex += cmdSize; - } else { - kernelIndex += cmdSize; - } - } - - return KERNEL_32; -} - - -/** - ** Locate the fisrt instance of _panic inside of _cpuid_set_info, and either remove it - ** Or replace it so that the cpuid is set to a valid value. - **/ -void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 impersonateModel) -{ - UInt8* bytes = (UInt8*)kernelData; - UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] - textAddress + textSection); - UInt32 jumpLocation = 0; - UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress; - if(kernelSymbolAddresses[SYMBOL_CPUID_SET_INFO] == 0) - { - printf("Unable to locate _cpuid_set_info\n"); - return; - - } - if(kernelSymbolAddresses[SYMBOL_PANIC] == 0) - { - printf("Unable to locate _panic\n"); - return; - } - - //TODO: don't assume it'll always work (Look for *next* function address in symtab and fail once it's been reached) - while( - (bytes[patchLocation -1] != 0xE8) || - ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | - bytes[patchLocation + 1] << 8 | - bytes[patchLocation + 2] << 16 | - bytes[patchLocation + 3] << 24))) - ) - { - patchLocation++; - } - patchLocation--; - - - // Remove panic call, just in case the following patch routines fail - bytes[patchLocation + 0] = 0x90; - bytes[patchLocation + 1] = 0x90; - bytes[patchLocation + 2] = 0x90; - bytes[patchLocation + 3] = 0x90; - bytes[patchLocation + 4] = 0x90; - - - // Locate the jump call, so that 10 bytes can be reclamed. - // NOTE: This will *NOT* be located on pre 10.6.2 kernels - jumpLocation = patchLocation - 15; - while((bytes[jumpLocation - 1] != 0x77 || - bytes[jumpLocation] != (patchLocation - jumpLocation - -8)) && - (patchLocation - jumpLocation) < 0xF0) - { - jumpLocation--; - } - - // If found... AND we want to impersonate a specific cpumodel / family... - if(impersonateFamily && - impersonateModel && - ((patchLocation - jumpLocation) < 0xF0)) - { - - bytes[jumpLocation] -= 10; // sizeof(movl $0x6b5a4cd2,0x00872eb4) = 10bytes - - /* - * Inpersonate the specified CPU FAMILY and CPU Model - */ - - // bytes[patchLocation - 17] = 0xC7; // already here... not needed to be done - // bytes[patchLocation - 16] = 0x05; // see above - UInt32 cpuid_cpufamily_addr = bytes[patchLocation - 15] << 0 | - bytes[patchLocation - 14] << 8 | - bytes[patchLocation - 13] << 16 | - bytes[patchLocation - 12] << 24; - - // NOTE: may change, determined based on cpuid_info struct - UInt32 cpuid_model_addr = cpuid_cpufamily_addr - 299; - - - // cpufamily = CPUFAMILY_INTEL_PENRYN - bytes[patchLocation - 11] = (impersonateFamily & 0x000000FF) >> 0; - bytes[patchLocation - 10] = (impersonateFamily & 0x0000FF00) >> 8; - bytes[patchLocation - 9] = (impersonateFamily & 0x00FF0000) >> 16; - bytes[patchLocation - 8] = (impersonateFamily & 0xFF000000) >> 24; - - // NOPS, just in case if the jmp call wasn't patched, we'll jump to a - // nop and continue with the rest of the patch - // Yay two free bytes :), 10 more can be reclamed if needed, as well as a few - // from the above code (only cpuid_model needs to be set. - bytes[patchLocation - 7] = 0x90; - bytes[patchLocation - 6] = 0x90; - - bytes[patchLocation - 5] = 0xC7; - bytes[patchLocation - 4] = 0x05; - bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0; - bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8; - bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16; - bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24; - - // Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes - // so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed. - bytes[patchLocation + 1] = impersonateModel; // cpuid_model - bytes[patchLocation + 2] = 0x01; // cpuid_extmodel - bytes[patchLocation + 3] = 0x00; // cpuid_extfamily - bytes[patchLocation + 4] = 0x02; // cpuid_stepping - - } - else if(impersonateFamily && impersonateModel) - { - // pre 10.6.2 kernel - // Locate the jump to directly *after* the panic call, - jumpLocation = patchLocation - 4; - while((bytes[jumpLocation - 1] != 0x77 || - bytes[jumpLocation] != (patchLocation - jumpLocation + 4)) && - (patchLocation - jumpLocation) < 0x20) - { - jumpLocation--; - } - // NOTE above isn't needed (I was going to use it, but I'm not, so instead, - // I'll just leave it to verify the binary stucture. - - // NOTE: the cpumodel_familt data is not set in _cpuid_set_info - // so we don't need to set it here, I'll get set later based on the model - // we set now. - - if((patchLocation - jumpLocation) < 0x20) - { - UInt32 cpuid_model_addr = (bytes[patchLocation - 14] << 0 | - bytes[patchLocation - 13] << 8 | - bytes[patchLocation - 12] << 16 | - bytes[patchLocation - 11] << 24); - // Remove jump - bytes[patchLocation - 9] = 0x90; /// Was a jump if supported cpu - bytes[patchLocation - 8] = 0x90; // jumped past the panic call, we want to override the panic - - bytes[patchLocation - 7] = 0x90; - bytes[patchLocation - 6] = 0x90; - - bytes[patchLocation - 5] = 0xC7; - bytes[patchLocation - 4] = 0x05; - bytes[patchLocation - 3] = (cpuid_model_addr & 0x000000FF) >> 0; - bytes[patchLocation - 2] = (cpuid_model_addr & 0x0000FF00) >> 8; - bytes[patchLocation - 1] = (cpuid_model_addr & 0x00FF0000) >> 16; - bytes[patchLocation - 0] = (cpuid_model_addr & 0xFF000000) >> 24; - - // Note: I could have just copied the 8bit cpuid_model in and saved about 4 bytes - // so if this function need a different patch it's still possible. Also, about ten bytes previous can be freed. - bytes[patchLocation + 1] = impersonateModel; // cpuid_model - bytes[patchLocation + 2] = 0x01; // cpuid_extmodel - bytes[patchLocation + 3] = 0x00; // cpuid_extfamily - bytes[patchLocation + 4] = 0x02; // cpuid_stepping - - - - patchLocation = jumpLocation; - // We now have 14 bytes available for a patch - - } - else - { - // Patching failed, using NOP replacement done initialy - } - } - else - { - // Either We were unable to change the jump call due to the function's sctructure - // changing, or the user did not request a patch. As such, resort to just - // removing the panic call (using NOP replacement above). Note that the - // IntelCPUPM kext may still panic due to the cpu's Model ID not being patched - } -} - - -/** - ** SleepEnabler.kext replacement (for those that need it) - ** Located the KERN_INVALID_ARGUMENT return and replace it with KERN_SUCCESS - **/ -void patch_pmCPUExitHaltToOff(void* kernelData) -{ - UInt8* bytes = (UInt8*)kernelData; - UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] - textAddress + textSection); - - if(kernelSymbolAddresses[SYMBOL_PMCPUEXITHALTTOOFF] == 0) - { - printf("Unable to locate _pmCPUExitHaltToOff\n"); - return; - } - - while(bytes[patchLocation - 1] != 0xB8 || - bytes[patchLocation] != 0x04 || // KERN_INVALID_ARGUMENT (0x00000004) - bytes[patchLocation + 1] != 0x00 || // KERN_INVALID_ARGUMENT - bytes[patchLocation + 2] != 0x00 || // KERN_INVALID_ARGUMENT - bytes[patchLocation + 3] != 0x00) // KERN_INVALID_ARGUMENT - - { - patchLocation++; - } - bytes[patchLocation] = 0x00; // KERN_SUCCESS; -} - -void patch_lapic_init(void* kernelData) -{ - UInt8 panicIndex = 0; - UInt8* bytes = (UInt8*)kernelData; - UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_LAPIC_INIT] - textAddress + textSection); - UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress; - - if(kernelSymbolAddresses[SYMBOL_LAPIC_INIT] == 0) - { - printf("Unable to locate %s\n", SYMBOL_LAPIC_INIT_STRING); - return; - - } - if(kernelSymbolAddresses[SYMBOL_PANIC] == 0) - { - printf("Unable to locate %s\n", SYMBOL_PANIC_STRING); - return; - } - - - - // Locate the (panicIndex + 1) panic call - while(panicIndex < 3) // Find the third panic call - { - while( - (bytes[patchLocation -1] != 0xE8) || - ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | - bytes[patchLocation + 1] << 8 | - bytes[patchLocation + 2] << 16 | - bytes[patchLocation + 3] << 24))) - ) - { - patchLocation++; - } - patchLocation++; - panicIndex++; - } - patchLocation--; // Remove extra increment from the < 3 while loop - - bytes[--patchLocation] = 0x90; - bytes[++patchLocation] = 0x90; - bytes[++patchLocation] = 0x90; - bytes[++patchLocation] = 0x90; - bytes[++patchLocation] = 0x90; - - -} - - -void patch_commpage_stuff_routine(void* kernelData) -{ - UInt8* bytes = (UInt8*)kernelData; - UInt32 patchLocation = (kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] - textAddress + textSection); - UInt32 panicAddr = kernelSymbolAddresses[SYMBOL_PANIC] - textAddress; - - if(kernelSymbolAddresses[SYMBOL_COMMPAGE_STUFF_ROUTINE] == 0) - { - printf("Unable to locate %s\n", SYMBOL_COMMPAGE_STUFF_ROUTINE_STRING); - return; - - } - if(kernelSymbolAddresses[SYMBOL_PANIC] == 0) - { - printf("Unable to locate %s\n", SYMBOL_PANIC_STRING); - return; - } - - - while( - (bytes[patchLocation -1] != 0xE8) || - ( ( (UInt32)(panicAddr - patchLocation - 4) + textSection ) != (UInt32)((bytes[patchLocation + 0] << 0 | - bytes[patchLocation + 1] << 8 | - bytes[patchLocation + 2] << 16 | - bytes[patchLocation + 3] << 24))) - ) - { - patchLocation++; - } - patchLocation--; - - - // Remove panic call, just in case the following patch routines fail - bytes[patchLocation + 0] = 0x90; - bytes[patchLocation + 1] = 0x90; - bytes[patchLocation + 2] = 0x90; - bytes[patchLocation + 3] = 0x90; - bytes[patchLocation + 4] = 0x90; - - -} Index: branches/meklort/i386/boot2/kernel_patcher.h =================================================================== --- branches/meklort/i386/boot2/kernel_patcher.h (revision 440) +++ branches/meklort/i386/boot2/kernel_patcher.h (revision 441) @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2009 Evan Lojewski. All rights reserved. - * - */ - -#include -#include - -#ifndef __BOOT2_KERNEL_PATCHER_H -#define __BOOT2_KERNEL_PATCHER_H - - -#define CPUID_MODEL_YONAH 14 -#define CPUID_MODEL_MEROM 15 -#define CPUID_MODEL_PENRYN 23 -#define CPUID_MODEL_NEHALEM 26 -#define CPUID_MODEL_ATOM 28 -#define CPUID_MODEL_FIELDS 30 /* Lynnfield, Clarksfield, Jasper */ -#define CPUID_MODEL_DALES 31 /* Havendale, Auburndale */ -#define CPUID_MODEL_NEHALEM_EX 46 - - -void patch_kernel(void* kernelData); - -#define KERNEL_64 1 -#define KERNEL_32 2 - -int locate_symbols(void* kernelData); - -void patch_kernel_32(void* kernelData); -void patch_kernel_64(void* kernelData); - - - -void patch_cpuid_set_info(void* kernelData, UInt32 impersonateFamily, UInt8 inpersonateModel); -void patch_pmCPUExitHaltToOff(void* kernelData); -void patch_lapic_init(void* kernelData); -void patch_commpage_stuff_routine(void* kernelData); -#endif /* !__BOOT2_KERNEL_PATCHER_H */