diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 811e203..649550c 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -595,6 +595,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch) { + u8 *section1 = (u8 *)firm + firm->section[1].offset; + u32 section1Size = firm->section[1].size; + u8 *arm9Section = (u8 *)firm + firm->section[3].offset; // Below 3.0, do not actually do anything. @@ -627,6 +630,8 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch) //Apply UNITINFO patch if(doUnitinfoPatch) ret += patchUnitInfoValueSet(arm9Section, kernel9Size); + ret += patchLgyK11(section1, section1Size); + // Also patch TwlBg here mergeSection0(TWL_FIRM, 0, loadFromStorage); firm->section[0].size = 0; diff --git a/arm9/source/patches.c b/arm9/source/patches.c index 80ca766..db11a44 100644 --- a/arm9/source/patches.c +++ b/arm9/source/patches.c @@ -808,4 +808,23 @@ void patchTwlBg(u8 *pos, u32 size) off2[i] = 0x46C0; } } -} \ No newline at end of file +} + +u32 patchLgyK11(u8 *section1, u32 section1Size) +{ + u32 *off; + + // Fix a bug where Legacy K11 maps user TLS with "user no access" permissions + // Map it as RWX (just like the rest of other user-accessible pages) instead + for (off = (u32 *)section1; (u8 *)off <= section1 + section1Size && *off != 0xE0100000; off++); + + if ((u8 *)off >= section1 + section1Size) + return 1; + + ++off; + + *off &= ~0x231; // clear APX mask and XN + *off |= 0x030; // re-set APX (to user/kernel RW) + + return 0; +} diff --git a/arm9/source/patches.h b/arm9/source/patches.h index 99c1f95..ed40aa9 100644 --- a/arm9/source/patches.h +++ b/arm9/source/patches.h @@ -67,3 +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);