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; 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) static inline u32 getSdmmc(u8 *pos, u32 size, u32 *sdmmc)
{ {
//Look for struct code //Look for struct code
@ -166,7 +184,7 @@ static inline u32 patchMpu(u8 *pos, u32 size)
return 0; 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; u8 *freeK9Space;
@ -186,7 +204,7 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
//Find and add the SDMMC struct //Find and add the SDMMC struct
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4); u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
u32 sdmmc; u32 sdmmc;
ret += getSdmmc(process9Offset, process9Size, &sdmmc); ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
if(!ret) *posSdmmc = sdmmc; if(!ret) *posSdmmc = sdmmc;
//Add EmuNAND hooks //Add EmuNAND hooks

View File

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

View File

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

View File

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

View File

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