Cleanup, re-enabled module patch on N3DS on 8.1, 9.0 and >= 11.0 FIRMs
This commit is contained in:
parent
b16539408b
commit
cce4a6d07f
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
117
source/patches.c
117
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
|
||||
|
@ -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);
|
Reference in New Issue
Block a user