From 6a2e1d4aa3771028e9751d182828c0f9c99fd315 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sat, 16 Sep 2023 19:45:06 +0200 Subject: [PATCH] Patch legacy k11 to allow exception dispatching --- arm9/source/firm.c | 4 +++- arm9/source/patches.c | 19 ++++++++++++++++++- arm9/source/patches.h | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 649550c..60044e4 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -597,6 +597,8 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch) { u8 *section1 = (u8 *)firm + firm->section[1].offset; u32 section1Size = firm->section[1].size; + u8 *section2 = (u8 *)firm + firm->section[2].offset; + u32 section2Size = firm->section[2].size; u8 *arm9Section = (u8 *)firm + firm->section[3].offset; @@ -630,7 +632,7 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch) //Apply UNITINFO patch if(doUnitinfoPatch) ret += patchUnitInfoValueSet(arm9Section, kernel9Size); - ret += patchLgyK11(section1, section1Size); + ret += patchLgyK11(section1, section1Size, section2, section2Size); // Also patch TwlBg here mergeSection0(TWL_FIRM, 0, loadFromStorage); diff --git a/arm9/source/patches.c b/arm9/source/patches.c index db11a44..4d7010a 100644 --- a/arm9/source/patches.c +++ b/arm9/source/patches.c @@ -810,7 +810,7 @@ void patchTwlBg(u8 *pos, u32 size) } } -u32 patchLgyK11(u8 *section1, u32 section1Size) +u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size) { u32 *off; @@ -826,5 +826,22 @@ u32 patchLgyK11(u8 *section1, u32 section1Size) *off &= ~0x231; // clear APX mask and XN *off |= 0x030; // re-set APX (to user/kernel RW) + // Patch two pointer-to-bool to point to a non-zero byte, enabling user exception handling. + // It is impossible to enable it by normal means, otherwise + for (off = (u32 *)section2; (u8 *)off <= section2 + section2Size && *off != 0x100021F; off++); + if ((u8 *)off >= section2 + section2Size) + return 1; + off[1] = 0xFFFF0F00; + off[2] = 0xFFFF0F04; + + // Dispatch-to-user code checks for memory block type and permissions (etc.), but + // LGY K11 doesn't do any memory management, so these checks will always fail. + // Patch with b +0x38 to skip all those checks + u16 *off2; + for (off2 = (u16 *)section2; (u8 *)off2 <= section2 + section2Size && (off2[0] != 0xDB1F || off2[1] != 0x4915); off2++); + if ((u8 *)off2 >= section2 + section2Size) + return 1; + *off2 = 0xE01A; + return 0; } diff --git a/arm9/source/patches.h b/arm9/source/patches.h index ed40aa9..b77d092 100644 --- a/arm9/source/patches.h +++ b/arm9/source/patches.h @@ -67,4 +67,4 @@ u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size); u32 patchTwlShaHashChecks(u8 *pos, u32 size); u32 patchAgbBootSplash(u8 *pos, u32 size); void patchTwlBg(u8 *pos, u32 size); // silently fails -u32 patchLgyK11(u8 *section1, u32 section1Size); +u32 patchLgyK11(u8 *section1, u32 section1Size, u8 *section2, u32 section2Size);