Support 3.x+ EmuNANDs and 3.x SysNANDs (partially), external FIRMs coming soonŧ

This commit is contained in:
Aurora Wright 2017-06-19 18:13:59 +02:00
parent 39ca23d609
commit 3f93bc5988
6 changed files with 56 additions and 49 deletions

View File

@ -114,6 +114,24 @@ static inline bool getFreeK9Space(u8 *pos, u32 size, u8 **freeK9Space)
return true;
}
static inline u32 getOldSdmmc(u32 *sdmmc, u32 firmVersion)
{
switch(firmVersion)
{
case 0x18:
*sdmmc = 0x080D91D8;
break;
case 0x1D:
case 0x1F:
*sdmmc = 0x080D8CD0;
break;
default:
return 1;
}
return 0;
}
static inline u32 getSdmmc(u8 *pos, u32 size, u32 *sdmmc)
{
//Look for struct code
@ -166,7 +184,7 @@ static inline u32 patchMpu(u8 *pos, u32 size)
return 0;
}
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address)
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address, u32 firmVersion)
{
u8 *freeK9Space;
@ -186,7 +204,7 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
//Find and add the SDMMC struct
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
u32 sdmmc;
ret += getSdmmc(process9Offset, process9Size, &sdmmc);
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
if(!ret) *posSdmmc = sdmmc;
//Add EmuNAND hooks

View File

@ -38,4 +38,4 @@ extern u32 emuOffset,
emuHeader;
void locateEmuNand(FirmwareSource *nandType);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address);
u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 process9Size, u8 *kernel9Address, u32 firmVersion);

View File

@ -155,30 +155,20 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
if(firmVersion == 0xFFFFFFFF) error("Failed to get the CTRNAND FIRM.");
bool mustLoadFromStorage = false;
if(!ISN3DS && *firmType == NATIVE_FIRM && !ISDEVUNIT)
if(!ISN3DS && *firmType == NATIVE_FIRM && !ISDEVUNIT && firmVersion < 0x18)
{
if(firmVersion < 0x18)
{
//We can't boot < 3.x EmuNANDs
if(nandType != FIRMWARE_SYSNAND)
error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it.");
//We can't boot < 3.x EmuNANDs
if(nandType != FIRMWARE_SYSNAND) error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it.");
if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM.");
if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM.");
*firmType = NATIVE_FIRM1X2X;
}
//We can't boot a 3.x/4.x NATIVE_FIRM EmuNAND, load one from SD/CTRNAND
//We can't boot a 3.x NATIVE_FIRM, load one from SD/CTRNAND too
else if(firmVersion < (nandType == FIRMWARE_SYSNAND ? 0x1D : 0x25)) mustLoadFromStorage = true;
*firmType = NATIVE_FIRM1X2X;
}
bool loadedFromStorage = false;
u32 firmSize;
if(loadFromStorage || mustLoadFromStorage)
if(loadFromStorage)
{
u32 result = loadFirmFromStorage(*firmType);
@ -191,7 +181,6 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
if(!loadedFromStorage)
{
if(mustLoadFromStorage) error("An old unsupported FIRM has been detected.\nCopy an external FIRM to boot.");
firmSize = decryptExeFs((Cxi *)firm);
if(!firmSize) error("Unable to decrypt the CTRNAND FIRM.");
}
@ -229,7 +218,7 @@ void loadHomebrewFirm(u32 pressed)
launchFirm((firm->reserved2[0] & 1) ? 2 : 1, argv);
}
static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage)
static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool loadFromStorage)
{
u32 srcModuleSize,
nbModules = 0;
@ -249,7 +238,7 @@ static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage)
srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200;
}
if(firmType == NATIVE_FIRM)
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
{
//2) Merge that info with our own modules'
for(u8 *src = (u8 *)0x1FF60000; src < (u8 *)(0x1FF60000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
@ -274,7 +263,7 @@ static inline void mergeSection0(FirmwareType firmType, bool loadFromStorage)
//3) Read or copy the modules
u8 *dst = firm->section[0].address;
const char *extModuleSizeError = "The external FIRM modules are too large.";
for(u32 i = 0, dstModuleSize, maxModuleSize = 0x60000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
for(u32 i = 0, dstModuleSize, maxModuleSize = firmType == NATIVE_FIRM ? 0x60000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize)
{
if(loadFromStorage)
{
@ -341,14 +330,18 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
ret = 0;
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
//Skip on FIRMs < 4.0
if(!ISN3DS || firmVersion >= 0x1D)
{
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
}
//Apply signature patches
ret += patchSignatureChecks(process9Offset, process9Size);
//Apply EmuNAND patches
if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(arm9Section, kernel9Size, process9Offset, process9Size, firm->section[2].address);
if(nandType != FIRMWARE_SYSNAND) ret += patchEmuNand(arm9Section, kernel9Size, process9Offset, process9Size, firm->section[2].address, firmVersion);
//Apply FIRM0/1 writes patches on SysNAND to protect A9LH
else ret += patchFirmWrites(process9Offset, process9Size);
@ -363,12 +356,8 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
ret += patchNandNcchEncryptionCheck(process9Offset, process9Size);
}
//11.0 FIRM patches
if(firmVersion >= (ISN3DS ? 0x21 : 0x52))
{
//Apply anti-anti-DG patches
ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
}
//Apply anti-anti-DG patches on 11.0+
if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
//Apply UNITINFO patches
if(doUnitinfoPatch)
@ -382,10 +371,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
ret += patchKernel9Panic(arm9Section, kernel9Size);
if(CONFIG(PATCHACCESS))
ret += patchP9AccessChecks(process9Offset, process9Size);
if(CONFIG(PATCHACCESS)) ret += patchP9AccessChecks(process9Offset, process9Size);
mergeSection0(NATIVE_FIRM, loadFromStorage);
mergeSection0(NATIVE_FIRM, firmVersion, loadFromStorage);
firm->section[0].size = 0;
return ret;
@ -423,14 +411,14 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
if(loadFromStorage)
{
mergeSection0(TWL_FIRM, true);
mergeSection0(TWL_FIRM, firmVersion, true);
firm->section[0].size = 0;
}
return ret;
}
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
u32 patchAgbFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
{
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
@ -457,7 +445,7 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
if(loadFromStorage)
{
mergeSection0(AGB_FIRM, true);
mergeSection0(AGB_FIRM, firmVersion, true);
firm->section[0].size = 0;
}

View File

@ -33,6 +33,6 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
void loadHomebrewFirm(u32 pressed);
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode, bool doUnitinfoPatch);
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
u32 patchAgbFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
u32 patch1x2xNativeAndSafeFirm(void);
void launchFirm(int argc, char **argv);

View File

@ -299,7 +299,7 @@ boot:
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
break;
case AGB_FIRM:
res = patchAgbFirm(loadFromStorage, doUnitinfoPatch);
res = patchAgbFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
break;
case SAFE_FIRM:
case SYSUPDATER_FIRM:

View File

@ -35,8 +35,8 @@
#include "draw.h"
#include "cache.h"
#include "fmt.h"
#include <stdarg.h>
#include "strings.h"
#include "fs.h"
static void startChrono(void)
{
@ -124,15 +124,15 @@ void wait(u64 amount)
void error(const char *fmt, ...)
{
char buf[DRAW_MAX_FORMATTED_STRING_SIZE + 1];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
if(!isFirmlaunch)
{
char buf[DRAW_MAX_FORMATTED_STRING_SIZE + 1];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
initScreens();
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
@ -141,6 +141,7 @@ void error(const char *fmt, ...)
waitInput(false);
}
else fileWrite(buf, "firmlauncherror.txt", strlen(buf));
mcuPowerOff();
}