Add support (firmprot and firmlaunch patches) for 2.x on sysNAND
This commit is contained in:
parent
a5c6b908b6
commit
83a0293af4
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user