From c63e46b1a9cb54803a27ea22a9d4af151290002a Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 18 Jul 2016 16:58:29 +0200 Subject: [PATCH] Added FIRM version detection, removed firmware.bin loading unless an unsupported O3DS NATIVE_FIRM (pre-5.0) is being loaded, skip patching old unsupported O3DS AGB/TWL FIRMs, only apply 11.0 patches with 11.0 or greater --- source/firm.c | 54 +++++++++++++++++++++++------------------------- source/firm.h | 4 ++-- source/fs.c | 20 +++++++++++++----- source/fs.h | 4 +++- source/patches.c | 15 ++++++-------- source/patches.h | 4 +++- 6 files changed, 55 insertions(+), 46 deletions(-) diff --git a/source/firm.c b/source/firm.c index 7b089a2..b34d795 100755 --- a/source/firm.c +++ b/source/firm.c @@ -218,18 +218,19 @@ void main(void) } } - loadFirm(firmType, firmType == NATIVE_FIRM && firmSource == ((updatedSys) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND)); + u32 firmVersion = loadFirm(firmType); switch(firmType) { case NATIVE_FIRM: - patchNativeFirm(nandType, emuHeader, isA9lh); + patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); break; case SAFE_FIRM: patchSafeFirm(); break; default: - patchLegacyFirm(firmType); + //Skip patching on unsupported O3DS AGB/TWL FIRMs + if(isN3DS || firmVersion >= (firmType == TWL_FIRM ? 0x16 : 0xB)) patchLegacyFirm(firmType); break; } @@ -242,29 +243,23 @@ void main(void) launchFirm(firmType, isFirmlaunch); } -static inline void loadFirm(FirmwareType firmType, bool externalFirm) +static inline u32 loadFirm(FirmwareType firmType) { section = firm->section; - bool externalFirmLoaded = externalFirm && - fileRead(firm, "/luma/firmware.bin") && - (((u32)section[2].address >> 8) & 0xFF) == (isN3DS ? 0x60 : 0x68); + //Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM + u32 firmVersion = firmRead(firm, (u32)firmType); - /* If the conditions to load the external FIRM aren't met, or reading fails, or the FIRM - doesn't match the console, load FIRM from CTRNAND */ - if(!externalFirmLoaded) + if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25) { - const char *firmFolders[4][2] = {{ "00000002", "20000002" }, - { "00000102", "20000102" }, - { "00000202", "20000202" }, - { "00000003", "20000003" }}; - - firmRead(firm, firmFolders[(u32)firmType][isN3DS ? 1 : 0]); - decryptExeFs((u8 *)firm); + if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) == (isN3DS ? 0x60 : 0x68)) mcuReboot(); } + else decryptExeFs((u8 *)firm); + + return firmVersion; } -static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool isA9lh) +static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh) { u8 *arm9Section = (u8 *)firm + section[2].offset; @@ -275,8 +270,8 @@ static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool firm->arm9Entry = (u8 *)0x801B01C; } - //Sets the 7.x NCCH KeyX and the 6.x gamecard save data KeyY - else if(!isA9lh) setRSAMod0DerivedKeys(); + //Sets the 7.x NCCH KeyX and the 6.x gamecard save data KeyY on >= 6.0 O3DS FIRMs, if not using A9LH + else if(!isA9lh && firmVersion >= 0x29) setRSAMod0DerivedKeys(); //Find the Process9 .code location, size and memory address u32 process9Size, @@ -299,11 +294,14 @@ static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool //Apply firmlaunch patches, not on 9.0 FIRM as it breaks firmlaunchhax patchFirmlaunches(process9Offset, process9Size, process9MemAddr); - //Apply anti-anti-DG patches for >= 11.0 firmwares - patchTitleInstallMinVersionCheck(process9Offset, process9Size); + //11.0 FIRM patches + if(firmVersion >= (isN3DS ? 0x21 : 0x52)) + { + //Apply anti-anti-DG patches + patchTitleInstallMinVersionCheck(process9Offset, process9Size); - //Does nothing if svcBackdoor is still there - reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size); + reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size); + } } static inline void patchLegacyFirm(FirmwareType firmType) @@ -315,7 +313,7 @@ static inline void patchLegacyFirm(FirmwareType firmType) firm->arm9Entry = (u8 *)0x801301C; } - applyLegacyFirmPatches((u8 *)firm, firmType, isN3DS); + applyLegacyFirmPatches((u8 *)firm, firmType); } static inline void patchSafeFirm(void) @@ -369,12 +367,12 @@ static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch) arm11 = (u32 *)0x1FFFFFF8; } - flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed - flushEntireICache(); - //Set ARM11 kernel entrypoint *arm11 = (u32)firm->arm11Entry; + flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed + flushEntireICache(); + //Final jump to ARM9 kernel ((void (*)())firm->arm9Entry)(); } \ No newline at end of file diff --git a/source/firm.h b/source/firm.h index 235b69d..404bc0f 100644 --- a/source/firm.h +++ b/source/firm.h @@ -53,8 +53,8 @@ typedef enum ConfigurationStatus CREATE_CONFIGURATION = 2 } ConfigurationStatus; -static inline void loadFirm(FirmwareType firmType, bool externalFirm); -static inline void patchNativeFirm(FirmwareSource nandType, u32 emuHeader, bool isA9lh); +static inline u32 loadFirm(FirmwareType firmType); +static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); static inline void copySection0AndInjectLoader(void); diff --git a/source/fs.c b/source/fs.c index 269d551..66210ed 100644 --- a/source/fs.c +++ b/source/fs.c @@ -106,14 +106,20 @@ void loadPayload(u32 pressed) flushDCacheRange(loaderAddress, loader_size); flushICacheRange(loaderAddress, loader_size); + ((void (*)())loaderAddress)(); } } -void firmRead(void *dest, const char *firmFolder) +u32 firmRead(void *dest, u32 firmType) { + const char *firmFolders[4][2] = {{ "00000002", "20000002" }, + { "00000102", "20000102" }, + { "00000202", "20000202" }, + { "00000003", "20000003" }}; + char path[48] = "1:/title/00040138/00000000/content"; - memcpy(&path[18], firmFolder, 8); + memcpy(&path[18], firmFolders[firmType][isN3DS ? 1 : 0], 8); DIR dir; FILINFO info; @@ -149,12 +155,16 @@ void firmRead(void *dest, const char *firmFolder) u32 i = 42; //Convert back the .app name from integer to array - while(id) + u32 tempId = id; + + while(tempId) { static const char hexDigits[] = "0123456789ABCDEF"; - path[i--] = hexDigits[id & 0xF]; - id >>= 4; + path[i--] = hexDigits[tempId & 0xF]; + tempId >>= 4; } fileRead(dest, path); + + return id; } \ No newline at end of file diff --git a/source/fs.h b/source/fs.h index a2ae92a..339d41a 100644 --- a/source/fs.h +++ b/source/fs.h @@ -26,8 +26,10 @@ #define PATTERN(a) a "_*.bin" +extern bool isN3DS; + bool mountFs(void); u32 fileRead(void *dest, const char *path); void fileWrite(const void *buffer, const char *path, u32 size); void loadPayload(u32 pressed); -void firmRead(void *dest, const char *firmFolder); \ No newline at end of file +u32 firmRead(void *dest, u32 firmType); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 2e9ab44..f4eb9ae 100644 --- a/source/patches.c +++ b/source/patches.c @@ -119,15 +119,12 @@ void reimplementSvcBackdoor(u8 *pos, u32 size) u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address while(*svcTable) svcTable++; //Look for SVC0 (NULL) - if(!svcTable[0x7B]) - { - u32 *freeSpace; - for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++); + u32 *freeSpace; + for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++); - memcpy(freeSpace, svcBackdoor, 40); + memcpy(freeSpace, svcBackdoor, 40); - svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage); - } + svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage); } void patchTitleInstallMinVersionCheck(u8 *pos, u32 size) @@ -136,10 +133,10 @@ void patchTitleInstallMinVersionCheck(u8 *pos, u32 size) u8 *off = memsearch(pos, pattern, size, 4); - if(off != NULL) off[4] = 0xE0; + off[4] = 0xE0; } -void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType, bool isN3DS) +void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType) { const patchData twlPatches[] = { {{0x1650C0, 0x165D64}, {{ 6, 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }}, 0}, diff --git a/source/patches.h b/source/patches.h index 8b75d26..5f36c14 100644 --- a/source/patches.h +++ b/source/patches.h @@ -33,6 +33,8 @@ typedef struct patchData { u32 type; } patchData; +extern bool isN3DS; + u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); @@ -40,5 +42,5 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); void patchFirmWriteSafe(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); -void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType, bool isN3DS); +void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); u32 getLoader(u8 *pos, u32 *loaderSize); \ No newline at end of file