From 3f93bc5988fd56104787c3c49cb0904792cdc64f Mon Sep 17 00:00:00 2001 From: Aurora Wright Date: Mon, 19 Jun 2017 18:13:59 +0200 Subject: [PATCH] =?UTF-8?q?Support=203.x+=20EmuNANDs=20and=203.x=20SysNAND?= =?UTF-8?q?s=20(partially),=20external=20FIRMs=20coming=20soon=C5=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/emunand.c | 22 ++++++++++++++++-- source/emunand.h | 2 +- source/firm.c | 58 +++++++++++++++++++----------------------------- source/firm.h | 2 +- source/main.c | 2 +- source/utils.c | 19 ++++++++-------- 6 files changed, 56 insertions(+), 49 deletions(-) diff --git a/source/emunand.c b/source/emunand.c index 36251b0..0cb23cc 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -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 diff --git a/source/emunand.h b/source/emunand.h index 99e605a..c4655e6 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -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); diff --git a/source/firm.c b/source/firm.c index 92558cd..c35156b 100755 --- a/source/firm.c +++ b/source/firm.c @@ -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; } diff --git a/source/firm.h b/source/firm.h index f9c7d38..4385b58 100644 --- a/source/firm.h +++ b/source/firm.h @@ -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); diff --git a/source/main.c b/source/main.c index b2d7b7a..0440a9a 100644 --- a/source/main.c +++ b/source/main.c @@ -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: diff --git a/source/utils.c b/source/utils.c index 0269c28..f27d27e 100644 --- a/source/utils.c +++ b/source/utils.c @@ -35,8 +35,8 @@ #include "draw.h" #include "cache.h" #include "fmt.h" - -#include +#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(); }