From a63fb971d42b33c25829068bb085d68add3818a4 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Fri, 6 May 2016 20:22:43 +0200 Subject: [PATCH] Add support for k9/p9 exception handling on all FIRMs --- source/firm.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- source/fs.c | 6 +----- source/fs.h | 2 +- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/source/firm.c b/source/firm.c index 37ebef4..4b8245e 100755 --- a/source/firm.c +++ b/source/firm.c @@ -24,6 +24,41 @@ u32 config, firmSource, emuOffset; +static inline void patchExceptionHandlersInstall(u8 *arm9Section) +{ + static 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] + + u32* off = (u32 *)(memsearch(arm9Section, pattern, section[2].size, sizeof(pattern))); + if(off == NULL) return; + off += sizeof(pattern)/4; + + u32 r0 = 0x08000000; + + for(; *off != 0xE3A01040; off++) //until mov r1, #0x40 + { + if((*off >> 26) != 0x39 || ((*off >> 16) & 0xf) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0) + continue; //discard everything that's not str rX, [r0, #imm](!) + + int rD = (*off >> 12) & 0xf; + int offset = (*off & 0xfff) * ((((*off >> 23) & 1) == 0) ? -1 : 1); + int writeback = (*off >> 21) & 1, pre = (*off >> 24) & 1; + + u32 addr = r0 + ((pre || !writeback) ? offset : 0); + if(addr != 0x08000014 && addr != 0x08000004) + *off = 0xE1A00000; //nop + else + *off = 0xE5800000 | (rD << 12) | (addr & 0xfff); //preserve IRQ and svc handlers + + if(!pre) addr += offset; + if(writeback) r0 = addr; + } +} + void main(void) { u32 bootType, @@ -72,7 +107,11 @@ void main(void) u32 devMode = CONFIG(5); - if(devMode) detectAndProcessExceptionDumps(); + if(devMode) + { + detectAndProcessExceptionDumps(); + installArm9Handlers(); + } bootType = 0; firmType = 0; @@ -139,7 +178,7 @@ void main(void) /* If L and R/A/Select or one of the single payload buttons are pressed, chainload an external payload */ if(devMode || (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS))) - loadPayload(pressed, devMode); + loadPayload(pressed); //If screens are inited or the corresponding option is set, load splash screen if(PDN_GPU_CNT != 1 || CONFIG(8)) loadSplash(); @@ -193,6 +232,8 @@ void main(void) loadFirm(firmType, !firmType && updatedSys == !firmSource); + patchExceptionHandlersInstall((u8 *)firm + section[2].offset); + switch(firmType) { case 0: diff --git a/source/fs.c b/source/fs.c index 5030ae3..13212a3 100644 --- a/source/fs.c +++ b/source/fs.c @@ -5,7 +5,6 @@ #include "fs.h" #include "memory.h" #include "screeninit.h" -#include "exceptions.h" #include "fatfs/ff.h" #include "buttons.h" #include "../build/loader.h" @@ -50,7 +49,7 @@ void fileWrite(const void *buffer, const char *path, u32 size) } } -void loadPayload(u32 pressed, u32 devMode) +void loadPayload(u32 pressed) { const char *pattern; @@ -76,9 +75,6 @@ void loadPayload(u32 pressed, u32 devMode) if(result == FR_OK && info.fname[0]) { - //Only when "Enable developer features" is set - if(devMode) installArm9Handlers(); - initScreens(); u32 *const loaderAddress = (u32 *)0x24FFFB00; diff --git a/source/fs.h b/source/fs.h index 065d440..6956148 100644 --- a/source/fs.h +++ b/source/fs.h @@ -12,5 +12,5 @@ u32 mountFs(void); u32 fileRead(void *dest, const char *path); void fileWrite(const void *buffer, const char *path, u32 size); void findDumpFile(const char *path, char *fileName); -void loadPayload(u32 pressed, u32 devMode); +void loadPayload(u32 pressed); void firmRead(void *dest, const char *firmFolder); \ No newline at end of file