From 83a0293af45abd18844a060d1eb75870d619f773 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Sun, 28 Aug 2016 00:32:47 +0200 Subject: [PATCH] Add support (firmprot and firmlaunch patches) for 2.x on sysNAND --- patches/reboot.s | 6 ++++-- source/firm.c | 45 ++++++++++++++++++++++++++------------------- source/firm.h | 4 ++-- source/patches.c | 2 +- source/patches.h | 2 +- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/patches/reboot.s b/patches/reboot.s index 9cb779f..35cb7fb 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -7,12 +7,14 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB .arm ; Interesting registers and locations to keep in mind, set just before this code is ran: ; - r1: FIRM path in exefs. - ; - r7: pointer to file object + ; - r7: pointer to file object (r10 on < 4.x; r7 is equal to 0 in that case) ; - *r7: vtable ; - *(vtable + 0x28): fread function - ; - *(r7 + 8): file handle + ; - *(r7 + 8) = r0: file handle mov r8, r1 + cmp r7, #0 + moveq r7, r10 pxi_wait_recv: ldr r2, =0x44846 diff --git a/source/firm.c b/source/firm.c index 7c9c0c4..385931b 100755 --- a/source/firm.c +++ b/source/firm.c @@ -40,14 +40,14 @@ extern u16 launchedFirmTIDLow[8]; //Defined in start.s static firmHeader *const firm = (firmHeader *)0x24000000; static const firmSectionHeader *section; -u32 emuOffset; +u32 emuOffset, firmVersion; bool isN3DS, isDevUnit, isFirmlaunch; cfgData configData; -FirmwareSource firmSource; +FirmwareSource firmSource, nandType; void main(void) { @@ -213,12 +213,12 @@ void main(void) writeConfig(configPath, configTemp); } - u32 firmVersion = loadFirm(firmType); + loadFirm(firmType); switch(firmType) { case NATIVE_FIRM: - patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); + patchNativeFirm(emuHeader, isA9lh); break; case SAFE_FIRM: patchSafeFirm(); @@ -232,37 +232,38 @@ void main(void) launchFirm(firmType); } -static inline u32 loadFirm(FirmwareType firmType) +static inline void loadFirm(FirmwareType firmType) { section = firm->section; //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); + firmVersion = firmRead(firm, (u32)firmType); if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25) { - //We can't boot < 3.x NANDs - if(firmVersion < 0x18) + //We can't boot < 2.x NANDs. No emuNAND either. + if(firmVersion < ((firmSource == FIRMWARE_SYSNAND) ? 9 : 0x18)) error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it."); //We can't boot a 4.x NATIVE_FIRM, load one from SD - if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) - error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot"); + else if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) + error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot."); //No assumption regarding FIRM version firmVersion = 0xffffffff; } - else decryptExeFs((u8 *)firm); + else if(!isN3DS && firmType == SAFE_FIRM && firmVersion < 1) + error("An old unsupported SAFE_FIRM has been detected."); - return firmVersion; + else decryptExeFs((u8 *)firm); } -static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh) +static inline void patchNativeFirm(u32 emuHeader, bool isA9lh) { u8 *arm9Section = (u8 *)firm + section[2].offset; u8 *arm11Section1 = (u8 *)firm + section[1].offset; - if(isN3DS) + if(firmVersion >= 0x37 && isN3DS) { //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader arm9Loader(arm9Section); @@ -277,6 +278,15 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); + //Apply firmlaunch patches + patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + + if(firmVersion < 0x18) // < 3.x + { + if(isA9lh) patchOldFirmWrites(process9Offset, process9Size); + return; + } + //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -290,9 +300,6 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 //Apply FIRM0/1 writes patches on sysNAND to protect A9LH else if(isA9lh) patchFirmWrites(process9Offset, process9Size); - //Apply firmlaunch patches - patchFirmlaunches(process9Offset, process9Size, process9MemAddr); - //11.0 FIRM patches if(firmVersion >= (isN3DS ? 0x21 : 0x52)) { @@ -333,7 +340,7 @@ static inline void patchSafeFirm(void) patchFirmWrites(arm9Section, section[2].size); } - else patchFirmWriteSafe(arm9Section, section[2].size); + else patchOldFirmWrites(arm9Section, section[2].size); } static inline void copySection0AndInjectSystemModules(void) @@ -371,7 +378,7 @@ static inline void launchFirm(FirmwareType firmType) { //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector u32 sectionNum; - if(firmType == NATIVE_FIRM) + if(firmType == NATIVE_FIRM && firmVersion >= 0x18) { copySection0AndInjectSystemModules(); sectionNum = 1; diff --git a/source/firm.h b/source/firm.h index 7b5d84d..a24b551 100644 --- a/source/firm.h +++ b/source/firm.h @@ -54,8 +54,8 @@ typedef enum ConfigurationStatus CREATE_CONFIGURATION = 2 } ConfigurationStatus; -static inline u32 loadFirm(FirmwareType firmType); -static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); +static inline void loadFirm(FirmwareType firmType); +static inline void patchNativeFirm(u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); static inline void copySection0AndInjectSystemModules(void); diff --git a/source/patches.c b/source/patches.c index 957a9b0..cdad593 100644 --- a/source/patches.c +++ b/source/patches.c @@ -113,7 +113,7 @@ void patchFirmWrites(u8 *pos, u32 size) off2[1] = writeBlock[1]; } -void patchFirmWriteSafe(u8 *pos, u32 size) +void patchOldFirmWrites(u8 *pos, u32 size) { const u16 writeBlockSafe[2] = {0x2400, 0xE01D}; diff --git a/source/patches.h b/source/patches.h index 24e82bb..8b6ccae 100644 --- a/source/patches.h +++ b/source/patches.h @@ -54,7 +54,7 @@ void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); -void patchFirmWriteSafe(u8 *pos, u32 size); +void patchOldFirmWrites(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);