From cce4a6d07f1a7358164b503a9007435cef15dd2b Mon Sep 17 00:00:00 2001 From: Aurora Date: Fri, 2 Sep 2016 22:43:15 +0200 Subject: [PATCH] Cleanup, re-enabled module patch on N3DS on 8.1, 9.0 and >= 11.0 FIRMs --- patches/k11modules.s | 8 --- source/config.c | 2 +- source/exceptions.h | 2 +- source/firm.c | 18 +++---- source/patches.c | 117 +++++++++++++++++-------------------------- source/patches.h | 6 +-- 6 files changed, 59 insertions(+), 94 deletions(-) diff --git a/patches/k11modules.s b/patches/k11modules.s index 900187f..b3718df 100644 --- a/patches/k11modules.s +++ b/patches/k11modules.s @@ -42,10 +42,6 @@ ; Save the value of all registers push {r0-r12} - ; Clear all the caches, just to be safe - mcr p15, 0, r6, c7, c14, 0 - mcr p15, 0, r6, c7, c5, 0 - ldr r0, [r0, #(0x80 - 0x7C)] ; Load the .text address ldr r7, [r4] ldr r2, [r7, #0x18] ; Load the size of the .text @@ -115,10 +111,6 @@ out: pop {r0-r12} ; Restore the registers we used - ; Clear all the caches again, just to be safe - mcr p15, 0, r6, c7, c14, 0 - mcr p15, 0, r6, c7, c5, 0 - ldr r0, [r4] ; Execute the instruction we overwrote in our detour bx lr ; Jump back to whoever called us diff --git a/source/config.c b/source/config.c index 671ef42..ccfbb7b 100644 --- a/source/config.c +++ b/source/config.c @@ -84,7 +84,7 @@ void configMenu(bool oldPinStatus) "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Display splash screen before payloads", "( ) Use a PIN", - "( ) Disable access checks (modules: O3DS only)" }; + "( ) Disable access checks" }; struct multiOption { int posXs[4]; diff --git a/source/exceptions.h b/source/exceptions.h index f21d91a..74bd152 100644 --- a/source/exceptions.h +++ b/source/exceptions.h @@ -24,7 +24,7 @@ #include "types.h" -#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) +#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) #define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) typedef struct __attribute__((packed)) diff --git a/source/firm.c b/source/firm.c index db100e3..b582bb8 100755 --- a/source/firm.c +++ b/source/firm.c @@ -350,19 +350,23 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 //Kernel9/Process9 debugging patchArm9ExceptionHandlersInstall(arm9Section, section[2].size); patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address); - patchKernel9Panic(arm9Section, section[2].size, NATIVE_FIRM); + patchKernel9Panic(arm9Section, section[2].size); //Stub svcBreak11 with "bkpt 65535" patchSvcBreak11(arm11Section1, arm11SvcTable); - //Stub kernel11panic with "bkpt 65534" + //Stub kernel11Panic with "bkpt 65534" patchKernel11Panic(arm11Section1, section[1].size); } if(CONFIG(9)) { patchArm11SvcAccessChecks(arm11SvcHandler); - if(!isN3DS) patchK11ModuleChecks(arm11Section1, section[1].size, &freeK11Space); + + //FIRMs between 9.3 and 10.4 don't have enough space on N3DS + if(!isN3DS || firmVersion <= 4 || firmVersion >= 0x21) + patchK11ModuleChecks(arm11Section1, section[1].size, &freeK11Space); + patchP9AccessChecks(process9Offset, process9Size); } } @@ -381,14 +385,6 @@ static inline void patchLegacyFirm(FirmwareType firmType) //Apply UNITINFO patch if(DEV_OPTIONS == 1) patchUnitInfoValueSet(arm9Section, section[3].size); - if(DEV_OPTIONS != 2) - { - //Kernel9/Process9 debugging - patchArm9ExceptionHandlersInstall(arm9Section, section[3].size); - patchSvcBreak9(arm9Section, section[3].size, (u32)section[3].address); - patchKernel9Panic(arm9Section, section[3].size, firmType); - } - applyLegacyFirmPatches((u8 *)firm, firmType); if(firmType == TWL_FIRM && CONFIG(5)) patchTwlBg((u8 *)firm + section[1].offset); diff --git a/source/patches.c b/source/patches.c index 6c27f31..97a5968 100644 --- a/source/patches.c +++ b/source/patches.c @@ -237,33 +237,11 @@ void patchTwlBg(u8 *pos) src2[1] = 0xE800 | ((((u32)dst - (u32)src2 - 4) & 0xFFF) >> 1); } -u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset) -{ - //This function has to succeed. Crash if it doesn't (we'll get an exception dump of it anyways) - - const u8 callExceptionDispatcherPattern[] = {0x0F, 0x00, 0xBD, 0xE8, 0x13, 0x00, 0x02, 0xF1}; - const u8 getTitleIDFromCodeSetPattern[] = {0xDC, 0x05, 0xC0, 0xE1, 0x20, 0x04, 0xA0, 0xE1}; - - u32 *loadCodeSet = (u32 *)memsearch(pos, getTitleIDFromCodeSetPattern, size, 8); - while((*loadCodeSet >> 20) != 0xE59 || ((*loadCodeSet >> 12) & 0xF) != 0) //ldr r0, [rX, #offset] - loadCodeSet--; - *codeSetOffset = *loadCodeSet & 0xFFF; - - return *((u32 *)memsearch(pos, callExceptionDispatcherPattern, size, 8) + 3); -} - void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size) { - const u8 pattern[] = { - 0x18, 0x10, 0x80, 0xE5, - 0x10, 0x10, 0x80, 0xE5, - 0x20, 0x10, 0x80, 0xE5, - 0x28, 0x10, 0x80, 0xE5, - }; //i.e when it stores ldr pc, [pc, #-4] + const u8 pattern[] = {0x03, 0xA0, 0xE3, 0x18}; - u32* off = (u32 *)(memsearch(pos, pattern, size, sizeof(pattern))); - if(off == NULL) return; - off += sizeof(pattern)/4; + u32* off = (u32 *)(memsearch(pos, pattern, size, 4) + 0x13); for(u32 r0 = 0x08000000; *off != 0xE3A01040; off++) //Until mov r1, #0x40 { @@ -286,13 +264,29 @@ void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size) } } +u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset) +{ + //This function has to succeed. Crash if it doesn't (we'll get an exception dump of it anyways) + + const u8 pattern[] = {0xE3, 0xDC, 0x05, 0xC0}, //Get TitleID from CodeSet + pattern2[] = {0xE1, 0x0F, 0x00, 0xBD}; //Call exception dispatcher + + u32 *loadCodeSet = (u32 *)(memsearch(pos, pattern, size, 4) - 0xB); + + *codeSetOffset = *loadCodeSet & 0xFFF; + + return *(u32 *)(memsearch(pos, pattern2, size, 4) + 0xD); +} + void patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address) { - //Stub svcBreak with "bkpt 65535" so we can debug the panic. - //Thanks @yellows8 and others for mentioning this idea on #3dsdev. - const u8 svcHandlerPattern[] = {0x00, 0xE0, 0x4F, 0xE1}; //mrs lr, spsr + /* Stub svcBreak with "bkpt 65535" so we can debug the panic. + Thanks @yellows8 and others for mentioning this idea on #3dsdev */ + + //Look for the svc handler + const u8 pattern[] = {0x00, 0xE0, 0x4F, 0xE1}; //mrs lr, spsr - u32 *arm9SvcTable = (u32 *)memsearch(pos, svcHandlerPattern, size, 4); + u32 *arm9SvcTable = (u32 *)memsearch(pos, pattern, size, 4); while(*arm9SvcTable) arm9SvcTable++; //Look for SVC0 (NULL) u32 *addr = (u32 *)(pos + arm9SvcTable[0x3C] - kernel9Address); @@ -306,75 +300,58 @@ void patchSvcBreak11(u8 *pos, u32 *arm11SvcTable) *addr = 0xE12FFF7F; } -void patchKernel9Panic(u8 *pos, u32 size, FirmwareType firmType) +void patchKernel9Panic(u8 *pos, u32 size) { - if(firmType == TWL_FIRM || firmType == AGB_FIRM) - { - u8 *off = pos + (isN3DS ? 0x723C : 0x69A8); - *(u16 *)off = 0x4778; //bx pc - *(u16 *)(off + 2) = 0x46C0; //nop - *(u32 *)(off + 4) = 0xE12FFF7E; //bkpt 65534 - } - else - { - const u8 pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x02, 0x30, 0xA0, 0xE1, 0x02, 0x10, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE3}; + const u8 pattern[] = {0xDF, 0xFF, 0xEA, 0x04}; - u32 *off = (u32 *)memsearch(pos, pattern, size, 16); - *off = 0xE12FFF7E; - } + u32 *off = (u32 *)(memsearch(pos, pattern, size, 4) - 0x11); + *off = 0xE12FFF7E; } void patchKernel11Panic(u8 *pos, u32 size) { - const u8 pattern[] = {0x02, 0x0B, 0x44, 0xE2, 0x00, 0x10, 0x90, 0xE5}; + const u8 pattern[] = {0x02, 0x0B, 0x44, 0xE2}; - u32 *off = (u32 *)memsearch(pos, pattern, size, 8); + u32 *off = (u32 *)memsearch(pos, pattern, size, 4); *off = 0xE12FFF7E; } +void patchP9AccessChecks(u8 *pos, u32 size) +{ + const u8 pattern[] = {0xE0, 0x00, 0x40, 0x39}; + + u16 *off = (u16 *)memsearch(pos, pattern, size, 4) - 7; + + off[0] = 0x2001; //mov r0, #1 + off[1] = 0x4770; //bx lr +} + void patchArm11SvcAccessChecks(u32 *arm11SvcHandler) { while(*arm11SvcHandler != 0xE11A0E1B) arm11SvcHandler++; //TST R10, R11,LSL LR *arm11SvcHandler = 0xE3B0A001; //MOVS R10, #1 } -//It's mainly Subv's code here: +//It's mainly Subv's code here void patchK11ModuleChecks(u8 *pos, u32 size, u8 **freeK11Space) { - //We have to detour a function in the ARM11 kernel because builtin modules - //are compressed in memory and are only decompressed at runtime. - - //Find the code that decompresses the .code section of the builtin modules and detour it with a jump to our code - const u8 pattern[] = { 0x00, 0x00, 0x94, 0xE5, 0x18, 0x10, 0x90, 0xE5, 0x28, 0x20, - 0x90, 0xE5, 0x48, 0x00, 0x9D, 0xE5 }; - - u32 *off = (u32 *)memsearch(pos, pattern, size, 16); - - //We couldn't find the code that decompresses the module - if(off == NULL) return; + /* We have to detour a function in the ARM11 kernel because builtin modules + are compressed in memory and are only decompressed at runtime */ //Inject our code into the free space memcpy(*freeK11Space, k11modules, k11modules_size); - //Inject a jump instruction to our code at the offset we found - //Construct a jump (BL) instruction to our code - u32 offset = ((((u32)*freeK11Space) - ((u32)off + 8)) >> 2) & 0xFFFFFF; + //Look for the code that decompresses the .code section of the builtin modules + const u8 pattern[] = {0xE5, 0x48, 0x00, 0x9D}; - *off = offset | (1 << 24) | (0x5 << 25) | (0xE << 28); + u32 *off = (u32 *)(memsearch(pos, pattern, size, 4) - 0xB); + + //Inject a jump (BL) instruction to our code at the offset we found + *off = 0xEB000000 | (((((u32)*freeK11Space) - ((u32)off + 8)) >> 2) & 0xFFFFFF); (*freeK11Space) += k11modules_size; } -void patchP9AccessChecks(u8 *pos, u32 size) -{ - const u8 pattern[] = {0xE0, 0x00, 0x40, 0x39, 0x08, 0x58}; - - u16 *off = (u16 *)memsearch(pos, pattern, size, 6) - 7; - - off[0] = 0x2001; //mov r0, #1 - off[1] = 0x4770; //bx lr -} - void patchUnitInfoValueSet(u8 *pos, u32 size) { //Look for UNITINFO value being set during kernel sync diff --git a/source/patches.h b/source/patches.h index a80a393..3e6c504 100644 --- a/source/patches.h +++ b/source/patches.h @@ -61,13 +61,13 @@ void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); void patchTwlBg(u8 *pos); -u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset); void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size); +u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset); void patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address); void patchSvcBreak11(u8 *pos, u32 *arm11SvcTable); -void patchKernel9Panic(u8 *pos, u32 size, FirmwareType firmType); +void patchKernel9Panic(u8 *pos, u32 size); void patchKernel11Panic(u8 *pos, u32 size); +void patchP9AccessChecks(u8 *pos, u32 size); void patchArm11SvcAccessChecks(u32 *arm11SvcHandler); void patchK11ModuleChecks(u8 *pos, u32 size, u8 **freeK11Space); -void patchP9AccessChecks(u8 *pos, u32 size); void patchUnitInfoValueSet(u8 *pos, u32 size); \ No newline at end of file