Add support (firmprot and firmlaunch patches) for 2.x on sysNAND

This commit is contained in:
TuxSH 2016-08-28 00:32:47 +02:00
parent a5c6b908b6
commit 83a0293af4
5 changed files with 34 additions and 25 deletions

View File

@ -7,12 +7,14 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB
.arm .arm
; Interesting registers and locations to keep in mind, set just before this code is ran: ; Interesting registers and locations to keep in mind, set just before this code is ran:
; - r1: FIRM path in exefs. ; - 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 ; - *r7: vtable
; - *(vtable + 0x28): fread function ; - *(vtable + 0x28): fread function
; - *(r7 + 8): file handle ; - *(r7 + 8) = r0: file handle
mov r8, r1 mov r8, r1
cmp r7, #0
moveq r7, r10
pxi_wait_recv: pxi_wait_recv:
ldr r2, =0x44846 ldr r2, =0x44846

View File

@ -40,14 +40,14 @@ extern u16 launchedFirmTIDLow[8]; //Defined in start.s
static firmHeader *const firm = (firmHeader *)0x24000000; static firmHeader *const firm = (firmHeader *)0x24000000;
static const firmSectionHeader *section; static const firmSectionHeader *section;
u32 emuOffset; u32 emuOffset, firmVersion;
bool isN3DS, bool isN3DS,
isDevUnit, isDevUnit,
isFirmlaunch; isFirmlaunch;
cfgData configData; cfgData configData;
FirmwareSource firmSource; FirmwareSource firmSource, nandType;
void main(void) void main(void)
{ {
@ -213,12 +213,12 @@ void main(void)
writeConfig(configPath, configTemp); writeConfig(configPath, configTemp);
} }
u32 firmVersion = loadFirm(firmType); loadFirm(firmType);
switch(firmType) switch(firmType)
{ {
case NATIVE_FIRM: case NATIVE_FIRM:
patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); patchNativeFirm(emuHeader, isA9lh);
break; break;
case SAFE_FIRM: case SAFE_FIRM:
patchSafeFirm(); patchSafeFirm();
@ -232,37 +232,38 @@ void main(void)
launchFirm(firmType); launchFirm(firmType);
} }
static inline u32 loadFirm(FirmwareType firmType) static inline void loadFirm(FirmwareType firmType)
{ {
section = firm->section; section = firm->section;
//Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM //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) if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25)
{ {
//We can't boot < 3.x NANDs //We can't boot < 2.x NANDs. No emuNAND either.
if(firmVersion < 0x18) if(firmVersion < ((firmSource == FIRMWARE_SYSNAND) ? 9 : 0x18))
error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it."); 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 //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) 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"); error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot.");
//No assumption regarding FIRM version //No assumption regarding FIRM version
firmVersion = 0xffffffff; 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 *arm9Section = (u8 *)firm + section[2].offset;
u8 *arm11Section1 = (u8 *)firm + section[1].offset; u8 *arm11Section1 = (u8 *)firm + section[1].offset;
if(isN3DS) if(firmVersion >= 0x37 && isN3DS)
{ {
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
arm9Loader(arm9Section); arm9Loader(arm9Section);
@ -277,6 +278,15 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
process9MemAddr; process9MemAddr;
u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &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 //Apply signature patches
patchSignatureChecks(process9Offset, process9Size); 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 //Apply FIRM0/1 writes patches on sysNAND to protect A9LH
else if(isA9lh) patchFirmWrites(process9Offset, process9Size); else if(isA9lh) patchFirmWrites(process9Offset, process9Size);
//Apply firmlaunch patches
patchFirmlaunches(process9Offset, process9Size, process9MemAddr);
//11.0 FIRM patches //11.0 FIRM patches
if(firmVersion >= (isN3DS ? 0x21 : 0x52)) if(firmVersion >= (isN3DS ? 0x21 : 0x52))
{ {
@ -333,7 +340,7 @@ static inline void patchSafeFirm(void)
patchFirmWrites(arm9Section, section[2].size); patchFirmWrites(arm9Section, section[2].size);
} }
else patchFirmWriteSafe(arm9Section, section[2].size); else patchOldFirmWrites(arm9Section, section[2].size);
} }
static inline void copySection0AndInjectSystemModules(void) 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 //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector
u32 sectionNum; u32 sectionNum;
if(firmType == NATIVE_FIRM) if(firmType == NATIVE_FIRM && firmVersion >= 0x18)
{ {
copySection0AndInjectSystemModules(); copySection0AndInjectSystemModules();
sectionNum = 1; sectionNum = 1;

View File

@ -54,8 +54,8 @@ typedef enum ConfigurationStatus
CREATE_CONFIGURATION = 2 CREATE_CONFIGURATION = 2
} ConfigurationStatus; } ConfigurationStatus;
static inline u32 loadFirm(FirmwareType firmType); static inline void loadFirm(FirmwareType firmType);
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchNativeFirm(u32 emuHeader, bool isA9lh);
static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchLegacyFirm(FirmwareType firmType);
static inline void patchSafeFirm(void); static inline void patchSafeFirm(void);
static inline void copySection0AndInjectSystemModules(void); static inline void copySection0AndInjectSystemModules(void);

View File

@ -113,7 +113,7 @@ void patchFirmWrites(u8 *pos, u32 size)
off2[1] = writeBlock[1]; off2[1] = writeBlock[1];
} }
void patchFirmWriteSafe(u8 *pos, u32 size) void patchOldFirmWrites(u8 *pos, u32 size)
{ {
const u16 writeBlockSafe[2] = {0x2400, 0xE01D}; const u16 writeBlockSafe[2] = {0x2400, 0xE01D};

View File

@ -54,7 +54,7 @@ void patchSignatureChecks(u8 *pos, u32 size);
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size);
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
void patchFirmWrites(u8 *pos, u32 size); 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 reimplementSvcBackdoor(u8 *pos, u32 size);
void implementSvcGetCFWInfo(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size);
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);