diff --git a/source/firm.c b/source/firm.c index 82dcb04..b77877d 100755 --- a/source/firm.c +++ b/source/firm.c @@ -242,7 +242,8 @@ static inline void loadFirm(u32 firmType, u32 externalFirm) static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) { u8 *arm9Section = (u8 *)firm + section[2].offset; - + u8 *arm11Section1 = (u8 *)firm + section[1].offset; + u32 nativeFirmType; if(console) @@ -296,6 +297,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) *(u16 *)sigOffset2 = sigPatch[0]; *((u16 *)sigOffset2 + 1) = sigPatch[1]; + reimplementSvcBackdoor(arm11Section1); //Does nothing if svcBackdoor is still there //Replace the FIRM loader with the injector while copying section0 copySection0AndInjectLoader(); } @@ -355,6 +357,41 @@ static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset) *pos_fopen = fOpenOffset; } +static inline void reimplementSvcBackdoor(u8 *arm11Section1) +{ + u32 *exceptionsPage = getExceptionVectorsPage(arm11Section1, section[1].size); + if(exceptionsPage == NULL) return; + + u32 low24 = (exceptionsPage[2] & 0x00FFFFFF) << 2; + u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension + int offset = (int)(low24 | signMask) + 8; //Branch offset + 8 for prefetch + + u32* svcTable = (u32 *)(arm11Section1 + *(u32 *)(arm11Section1 + 0xFFFF0008 + offset - 0xFFF00000 + 8) - 0xFFF00000); //svc handler address + while(*svcTable != 0) svcTable++; //svc0 = NULL + + if(svcTable[0x7B] != 0) return; + + u32 *freeSpace = exceptionsPage; + while(freeSpace < exceptionsPage + 0x400 && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF)) + freeSpace++; + + if(freeSpace >= exceptionsPage + 0x400) return; + + //Official implementation of svcBackdoor + freeSpace[0] = 0xE3CD10FF; + freeSpace[1] = 0xE3811C0F; + freeSpace[2] = 0xE2811028; + freeSpace[3] = 0xE5912000; + freeSpace[4] = 0xE9226000; + freeSpace[5] = 0xE1A0D002; + freeSpace[6] = 0xE12FFF30; + freeSpace[7] = 0xE8BD0003; + freeSpace[8] = 0xE1A0D000; + freeSpace[9] = 0xE12FFF11; + + svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *) exceptionsPage); +} + static inline void copySection0AndInjectLoader(void) { u8 *arm11Section0 = (u8 *)firm + section[0].offset; diff --git a/source/firm.h b/source/firm.h index 8a88b23..5ef2549 100644 --- a/source/firm.h +++ b/source/firm.h @@ -41,6 +41,7 @@ static inline void loadFirm(u32 firmType, u32 externalFirm); static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode); static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader); static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset); +static inline void reimplementSvcBackdoor(u8 *arm11Section1); static inline void copySection0AndInjectLoader(void); static inline void patchLegacyFirm(u32 firmType); static inline void patchSafeFirm(void); diff --git a/source/patches.c b/source/patches.c index 62d4e67..40b9929 100644 --- a/source/patches.c +++ b/source/patches.c @@ -87,4 +87,11 @@ u32 getLoader(u8 *pos, u32 *loaderSize) *loaderSize = size; return (u32)(off - pos); -} \ No newline at end of file +} + +u32* getExceptionVectorsPage(u8 *pos, u32 size) +{ + const u8 pattern[] = {0x00,0xB0,0x9C,0xE5,0x0A,0xB0,0x0B,0xE0,0x0A,0x00,0x5B,0xE1,0xFB,0xFF,0xFF,0x1A}; + + return (u32 *)(memsearch(pos, pattern, size, 16) - 0x2C); +} diff --git a/source/patches.h b/source/patches.h index 78de1fc..31736da 100644 --- a/source/patches.h +++ b/source/patches.h @@ -24,4 +24,6 @@ void *getReboot(u8 *pos, u32 size); u32 getfOpen(u8 *proc9Offset, void *rebootOffset); u16 *getFirmWrite(u8 *pos, u32 size); u16 *getFirmWriteSafe(u8 *pos, u32 size); -u32 getLoader(u8 *pos, u32 *loaderSize); \ No newline at end of file + +u32 getLoader(u8 *pos, u32 *loaderSize); +u32* getExceptionVectorsPage(u8 *pos, u32 size); //Multi-purpose, don't change