|
|
|
|
@@ -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;
|
|
|
|
|
|