diff --git a/injector/source/CFWInfo.h b/injector/source/CFWInfo.h index 69bd260..17f00c7 100644 --- a/injector/source/CFWInfo.h +++ b/injector/source/CFWInfo.h @@ -9,7 +9,7 @@ typedef struct __attribute__((packed)) u8 versionMajor; u8 versionMinor; u8 versionBuild; - u8 flags; /* bit 0: dev branch; bit 1: is release */ + u8 flags; u32 commitHash; diff --git a/injector/source/loader.c b/injector/source/loader.c index 5503016..5783a4a 100644 --- a/injector/source/loader.c +++ b/injector/source/loader.c @@ -155,8 +155,10 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i lzss_decompress((u8 *)shared->text_addr + size); } + u16 progver = g_exheader.codesetinfo.flags.remasterversion[1] | (g_exheader.codesetinfo.flags.remasterversion[0] << 8); + // patch - patchCode(progid, (u8 *)shared->text_addr, shared->total_size << 12); + patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12); return 0; } diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 3e518cf..bd885f0 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -43,7 +43,7 @@ static Result openLumaFile(IFile *file, const char *path) return res; } -static void loadCFWInfo(void) +static inline void loadCFWInfo(void) { static bool infoLoaded = false; @@ -52,7 +52,7 @@ static void loadCFWInfo(void) svcGetCFWInfo(&info); IFile file; - if(BOOTCFG_SAFEMODE != 0 && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted + if(LOADERFLAG(ISSAFEMODE) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted IFile_Close(&file); infoLoaded = true; @@ -320,135 +320,105 @@ static void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOff } } -void patchCode(u64 progId, u8 *code, u32 size) +void patchCode(u64 progId, u16 progVer, u8 *code, u32 size) { loadCFWInfo(); - switch(progId) + if(((progId == 0x0004003000008F02LL || //USA Home Menu + progId == 0x0004003000008202LL || //JPN Home Menu + progId == 0x0004003000009802LL) //EUR Home Menu + && progVer > 4) || + (progId == 0x000400300000A902LL //KOR Home Menu + && progVer > 0) || + progId == 0x000400300000A102LL || //CHN Home Menu + progId == 0x000400300000B102LL) //TWN Home Menu { - case 0x0004003000008F02LL: // USA Menu - case 0x0004003000008202LL: // EUR Menu - case 0x0004003000009802LL: // JPN Menu - case 0x000400300000A102LL: // CHN Menu - case 0x000400300000A902LL: // KOR Menu - case 0x000400300000B102LL: // TWN Menu + static const u8 regionFreePattern[] = { + 0x0A, 0x0C, 0x00, 0x10 + }, + regionFreePatch[] = { + 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 + }; + + //Patch SMDH region checks + patchMemory(code, size, + regionFreePattern, + sizeof(regionFreePattern), -31, + regionFreePatch, + sizeof(regionFreePatch), 1 + ); + } + + else if(progId == 0x0004013000003202LL) // FRIENDS + { + static const u8 fpdVerPattern[] = { + 0x42, 0xE0, 0x1E, 0xFF + }; + + u8 mostRecentFpdVer = 8; + + u8 *off = memsearch(code, fpdVerPattern, size, sizeof(fpdVerPattern)); + + if(off == NULL) svcBreak(USERBREAK_ASSERT); + + //Allow online access to work with old friends modules + if(off[0xA] < mostRecentFpdVer) off[0xA] = mostRecentFpdVer; + } + + else if((progId == 0x0004001000021000LL || // USA MSET + progId == 0x0004001000020000LL || // JPN MSET + progId == 0x0004001000022000LL || // EUR MSET + progId == 0x0004001000026000LL || // CHN MSET + progId == 0x0004001000027000LL || // KOR MSET + progId == 0x0004001000028000LL) // TWN MSET + && CONFIG(PATCHVERSTRING)) + { + static const u16 verPattern[] = u"Ve"; + static u16 *verString; + u32 verStringSize = 0, + currentNand = BOOTCFG_NAND; + + u16 customVerString[19]; + loadCustomVerString(customVerString, &verStringSize, currentNand); + + if(verStringSize != 0) verString = customVerString; + else { - static const u8 regionFreePattern[] = { - 0x0A, 0x0C, 0x00, 0x10 - }, - regionFreePatch[] = { - 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - }; + verStringSize = 8; + u32 currentFirm = BOOTCFG_FIRM; - //Patch SMDH region checks - patchMemory(code, size, - regionFreePattern, - sizeof(regionFreePattern), -31, - regionFreePatch, - sizeof(regionFreePatch), 1 - ); + static u16 *verStringsNands[] = { u" Sys", + u" Emu", + u"Emu2", + u"Emu3", + u"Emu4" }, - break; + *verStringsEmuSys[] = { u"EmuS", + u"Em2S", + u"Em3S", + u"Em4S" }, + + *verStringsSysEmu[] = { u"SysE", + u"SyE2", + u"SyE3", + u"SyE4" }; + + verString = (currentFirm != 0) == (currentNand != 0) ? verStringsNands[currentNand] : + (!currentNand ? verStringsSysEmu[currentFirm - 1] : verStringsEmuSys[currentNand - 1]); } - case 0x0004013000002C02LL: // NIM - { - //Apply only if the user booted with R - if((BOOTCFG_NAND != 0) != (BOOTCFG_FIRM != 0)) - { - static const u8 skipEshopUpdateCheckPattern[] = { - 0x30, 0xB5, 0xF1, 0xB0 - }, - skipEshopUpdateCheckPatch[] = { - 0x00, 0x20, 0x08, 0x60, 0x70, 0x47 - }; + //Patch Ver. string + patchMemory(code, size, + verPattern, + sizeof(verPattern) - 2, 0, + verString, + verStringSize, 1 + ); + } - //Skip update checks to access the EShop - patchMemory(code, size, - skipEshopUpdateCheckPattern, - sizeof(skipEshopUpdateCheckPattern), 0, - skipEshopUpdateCheckPatch, - sizeof(skipEshopUpdateCheckPatch), 1 - ); - } - - break; - } - - case 0x0004013000003202LL: // FRIENDS - { - static const u8 fpdVerPattern[] = { - 0x42, 0xE0, 0x1E, 0xFF - }; - - u8 mostRecentFpdVer = 8; - - u8 *fpdVer = memsearch(code, fpdVerPattern, size, sizeof(fpdVerPattern)); - - if(fpdVer == NULL) svcBreak(USERBREAK_ASSERT); - - //Allow online access to work with old friends modules - if(fpdVer[0xA] < mostRecentFpdVer) fpdVer[0xA] = mostRecentFpdVer; - - break; - } - - case 0x0004001000021000LL: // USA MSET - case 0x0004001000020000LL: // JPN MSET - case 0x0004001000022000LL: // EUR MSET - case 0x0004001000026000LL: // CHN MSET - case 0x0004001000027000LL: // KOR MSET - case 0x0004001000028000LL: // TWN MSET - { - if(CONFIG(PATCHVERSTRING)) - { - static const u16 verPattern[] = u"Ve"; - static u16 *verString; - u32 verStringSize = 0, - currentNand = BOOTCFG_NAND; - - u16 customVerString[19]; - loadCustomVerString(customVerString, &verStringSize, currentNand); - - if(verStringSize != 0) verString = customVerString; - else - { - verStringSize = 8; - u32 currentFirm = BOOTCFG_FIRM; - - static u16 *verStringsNands[] = { u" Sys", - u" Emu", - u"Emu2", - u"Emu3", - u"Emu4" }, - - *verStringsEmuSys[] = { u"EmuS", - u"Em2S", - u"Em3S", - u"Em4S" }, - - *verStringsSysEmu[] = { u"SysE", - u"SyE2", - u"SyE3", - u"SyE4" }; - - verString = (currentFirm != 0) == (currentNand != 0) ? verStringsNands[currentNand] : - (!currentNand ? verStringsSysEmu[currentFirm - 1] : verStringsEmuSys[currentNand - 1]); - } - - //Patch Ver. string - patchMemory(code, size, - verPattern, - sizeof(verPattern) - 2, 0, - verString, - verStringSize, 1 - ); - } - - break; - } - - case 0x0004013000008002LL: // NS + else if(progId == 0x0004013000008002LL) // NS + { + if(progVer >= 0xD) { static const u8 stopCartUpdatesPattern[] = { 0x0C, 0x18, 0xE1, 0xD8 @@ -464,162 +434,148 @@ void patchCode(u64 progId, u8 *code, u32 size) stopCartUpdatesPatch, sizeof(stopCartUpdatesPatch), 2 ); + } + if(LOADERFLAG(ISN3DS)) + { u32 cpuSetting = MULTICONFIG(NEWCPU); if(cpuSetting != 0) { static const u8 cfgN3dsCpuPattern[] = { - 0x00, 0x40, 0xA0, 0xE1, 0x07 + 0x0C, 0x00, 0x94, 0x15 }; - u32 *cfgN3dsCpuLoc = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern)); + u32 *off = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern)); - if(cfgN3dsCpuLoc == NULL) svcBreak(USERBREAK_ASSERT); + if(off == NULL) svcBreak(USERBREAK_ASSERT); //Patch N3DS CPU Clock and L2 cache setting - *(cfgN3dsCpuLoc + 1) = 0xE1A00000; - *(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting; + *(off - 4) = 0xE1A00000; + *(off + 3) = 0xE3A00000 | cpuSetting; } - - break; } + } - case 0x0004013000001702LL: // CFG + else if(progId == 0x0004013000001702LL) // CFG + { + static const u8 secureinfoSigCheckPattern[] = { + 0x06, 0x46, 0x10, 0x48 + }, + secureinfoSigCheckPatch[] = { + 0x00, 0x26 + }; + + //Disable SecureInfo signature check + patchMemory(code, size, + secureinfoSigCheckPattern, + sizeof(secureinfoSigCheckPattern), 0, + secureinfoSigCheckPatch, + sizeof(secureinfoSigCheckPatch), 1 + ); + + if(secureInfoExists()) { - static const u8 secureinfoSigCheckPattern[] = { - 0x06, 0x46, 0x10, 0x48 - }, - secureinfoSigCheckPatch[] = { - 0x00, 0x26 - }; + static const u16 secureinfoFilenamePattern[] = u"SecureInfo_", + secureinfoFilenamePatch[] = u"C"; - //Disable SecureInfo signature check + //Use SecureInfo_C patchMemory(code, size, - secureinfoSigCheckPattern, - sizeof(secureinfoSigCheckPattern), 0, - secureinfoSigCheckPatch, - sizeof(secureinfoSigCheckPatch), 1 + secureinfoFilenamePattern, + sizeof(secureinfoFilenamePattern) - 2, + sizeof(secureinfoFilenamePattern) - 2, + secureinfoFilenamePatch, + sizeof(secureinfoFilenamePatch) - 2, 2 ); - - if(secureInfoExists()) - { - static const u16 secureinfoFilenamePattern[] = u"SecureInfo_", - secureinfoFilenamePatch[] = u"C"; - - //Use SecureInfo_C - patchMemory(code, size, - secureinfoFilenamePattern, - sizeof(secureinfoFilenamePattern) - 2, - sizeof(secureinfoFilenamePattern) - 2, - secureinfoFilenamePatch, - sizeof(secureinfoFilenamePatch) - 2, 2 - ); - } - - break; } + } - case 0x0004013000003702LL: // RO + else if(progId == 0x0004013000003702LL && progVer >= 1) // RO + { + static const u8 sigCheckPattern[] = { + 0x20, 0xA0, 0xE1, 0x8B + }, + sha256ChecksPattern1[] = { + 0xE1, 0x30, 0x40, 0x2D + }, + sha256ChecksPattern2[] = { + 0x2D, 0xE9, 0x01, 0x70 + }, + stub[] = { + 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 // mov r0, #0; bx lr + }; + + //Disable CRR0 signature (RSA2048 with SHA256) check + patchMemory(code, size, + sigCheckPattern, + sizeof(sigCheckPattern), -9, + stub, + sizeof(stub), 1 + ); + + //Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table) + patchMemory(code, size, + sha256ChecksPattern1, + sizeof(sha256ChecksPattern1), 1, + stub, + sizeof(stub), 1 + ); + + patchMemory(code, size, + sha256ChecksPattern2, + sizeof(sha256ChecksPattern2), -2, + stub, + sizeof(stub), 1 + ); + } + + else if(progId == 0x0004003000008A02LL && MULTICONFIG(DEVOPTIONS) == 1) // ErrDisp + { + static const u8 unitinfoCheckPattern1[] = { + 0x00, 0xD0, 0xE5, 0xDB + }, + unitinfoCheckPattern2[] = { + 0x14, 0x00, 0xD0, 0xE5, 0x01 + }, + unitinfoCheckPatch[] = { + 0x00, 0x00, 0xA0, 0xE3 + }; + + patchMemory(code, size, + unitinfoCheckPattern1, + sizeof(unitinfoCheckPattern1), -1, + unitinfoCheckPatch, + sizeof(unitinfoCheckPatch), 1 + ); + + patchMemory(code, size, + unitinfoCheckPattern2, + sizeof(unitinfoCheckPattern2), 0, + unitinfoCheckPatch, + sizeof(unitinfoCheckPatch), 3 + ); + } + + else if(CONFIG(USELANGEMUANDCODE) && (u32)((progId & 0xFFFFFFF000000000LL) >> 0x24) == 0x0004000) + { + //External .code section loading + loadTitleCodeSection(progId, code, size); + + //Language emulation + u8 regionId = 0xFF, + languageId = 0xFF; + loadTitleLocaleConfig(progId, ®ionId, &languageId); + + if(regionId != 0xFF || regionId != 0xFF) { - static const u8 sigCheckPattern[] = { - 0x20, 0xA0, 0xE1, 0x8B - }, - sha256ChecksPattern1[] = { - 0xE1, 0x30, 0x40, 0x2D - }, - sha256ChecksPattern2[] = { - 0x2D, 0xE9, 0x01, 0x70 - }, - stub[] = { - 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 // mov r0, #0; bx lr - }; + u32 CFGUHandleOffset; + u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset); - //Disable CRR0 signature (RSA2048 with SHA256) check - patchMemory(code, size, - sigCheckPattern, - sizeof(sigCheckPattern), -9, - stub, - sizeof(stub), 1 - ); - - //Disable CRO0/CRR0 SHA256 hash checks (section hashes, and hash table) - patchMemory(code, size, - sha256ChecksPattern1, - sizeof(sha256ChecksPattern1), 1, - stub, - sizeof(stub), 1 - ); - - patchMemory(code, size, - sha256ChecksPattern2, - sizeof(sha256ChecksPattern2), -2, - stub, - sizeof(stub), 1 - ); - - break; - } - - case 0x0004003000008A02LL: // ErrDisp - { - if(MULTICONFIG(DEVOPTIONS) == 1) + if(CFGU_GetConfigInfoBlk2_endPos != NULL) { - static const u8 unitinfoCheckPattern1[] = { - 0x00, 0xD0, 0xE5, 0xDB - }, - unitinfoCheckPattern2[] = { - 0x14, 0x00, 0xD0, 0xE5, 0x01 - }, - unitinfoCheckPatch[] = { - 0x00, 0x00, 0xA0, 0xE3 - } ; - - patchMemory(code, size, - unitinfoCheckPattern1, - sizeof(unitinfoCheckPattern1), -1, - unitinfoCheckPatch, - sizeof(unitinfoCheckPatch), 1 - ); - - patchMemory(code, size, - unitinfoCheckPattern2, - sizeof(unitinfoCheckPattern2), 0, - unitinfoCheckPatch, - sizeof(unitinfoCheckPatch), 3 - ); + if(languageId != 0xFF) patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos); + if(regionId != 0xFF) patchCfgGetRegion(code, size, regionId, CFGUHandleOffset); } - - break; } - - default: - if(CONFIG(USELANGEMUANDCODE)) - { - if((u32)((progId & 0xFFFFFFF000000000LL) >> 0x24) == 0x0004000) - { - //External .code section loading - loadTitleCodeSection(progId, code, size); - - //Language emulation - u8 regionId = 0xFF, - languageId = 0xFF; - loadTitleLocaleConfig(progId, ®ionId, &languageId); - - if(regionId != 0xFF || regionId != 0xFF) - { - u32 CFGUHandleOffset; - u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset); - - if(CFGU_GetConfigInfoBlk2_endPos != NULL) - { - if(languageId != 0xFF) patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos); - if(regionId != 0xFF) patchCfgGetRegion(code, size, regionId, CFGUHandleOffset); - } - } - } - } - - break; } } \ No newline at end of file diff --git a/injector/source/patcher.h b/injector/source/patcher.h index 3f48c88..d7c8ac8 100644 --- a/injector/source/patcher.h +++ b/injector/source/patcher.h @@ -2,15 +2,15 @@ #include <3ds/types.h> -#define CONFIG(a) (((info.config >> (a + 21)) & 1) != 0) -#define MULTICONFIG(a) ((info.config >> (a * 2 + 9)) & 3) +#define CONFIG(a) (((info.config >> (a + 20)) & 1) != 0) +#define MULTICONFIG(a) ((info.config >> (a * 2 + 8)) & 3) #define BOOTCONFIG(a, b) ((info.config >> a) & b) +#define LOADERFLAG(a) ((info.flags >> (a + 4)) & 1) != 0 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) #define BOOTCFG_A9LH BOOTCONFIG(6, 1) #define BOOTCFG_NOFORCEFLAG BOOTCONFIG(7, 1) -#define BOOTCFG_SAFEMODE BOOTCONFIG(8, 1) enum multiOptions { @@ -34,4 +34,10 @@ enum singleOptions PATCHACCESS }; -void patchCode(u64 progId, u8 *code, u32 size); \ No newline at end of file +enum flags +{ + ISN3DS = 0, + ISSAFEMODE +}; + +void patchCode(u64 progId, u16 progVer, u8 *code, u32 size); \ No newline at end of file diff --git a/source/config.c b/source/config.c index cd13741..2a539cf 100644 --- a/source/config.c +++ b/source/config.c @@ -62,7 +62,7 @@ void writeConfig(ConfigurationStatus needConfig, u32 configTemp) } //Merge the new options and new boot configuration - configData.config = (configData.config & 0xFFFFFE00) | (configTemp & 0x1FF); + configData.config = (configData.config & 0xFFFFFF00) | (configTemp & 0xFF); if(!fileWrite(&configData, CONFIG_FILE, sizeof(CfgData))) error("Error writing the configuration file"); @@ -377,9 +377,9 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) //Parse and write the new configuration for(u32 i = 0; i < multiOptionsAmount; i++) - configData.config |= multiOptions[i].enabled << (i * 2 + 9); + configData.config |= multiOptions[i].enabled << (i * 2 + 8); for(u32 i = 0; i < singleOptionsAmount; i++) - configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 21); + configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 20); u32 newPinMode = MULTICONFIG(PIN); diff --git a/source/config.h b/source/config.h index 9a710b5..10fe496 100644 --- a/source/config.h +++ b/source/config.h @@ -24,19 +24,18 @@ #include "types.h" -#define CONFIG(a) (((configData.config >> (a + 21)) & 1) != 0) -#define MULTICONFIG(a) ((configData.config >> (a * 2 + 9)) & 3) +#define CONFIG(a) (((configData.config >> (a + 20)) & 1) != 0) +#define MULTICONFIG(a) ((configData.config >> (a * 2 + 8)) & 3) #define BOOTCONFIG(a, b) ((configData.config >> a) & b) #define CONFIG_FILE "config.bin" #define CONFIG_VERSIONMAJOR 1 -#define CONFIG_VERSIONMINOR 6 +#define CONFIG_VERSIONMINOR 7 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) #define BOOTCFG_A9LH BOOTCONFIG(6, 1) #define BOOTCFG_NOFORCEFLAG BOOTCONFIG(7, 1) -#define BOOTCFG_SAFEMODE BOOTCONFIG(8, 1) enum multiOptions { diff --git a/source/firm.c b/source/firm.c index 9ce909f..386eb1c 100755 --- a/source/firm.c +++ b/source/firm.c @@ -36,7 +36,7 @@ static Firm *firm = (Firm *)0x24000000; -u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage) +u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode) { const char *firmwareFiles[] = { "firmware.bin", @@ -66,7 +66,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora if(nandType != FIRMWARE_SYSNAND) error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it."); - if(BOOTCFG_SAFEMODE != 0) 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; } @@ -109,7 +109,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora return firmVersion; } -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lhInstalled, u32 devMode) +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lhInstalled, bool isSafeMode, u32 devMode) { u8 *arm9Section = (u8 *)firm + firm->section[2].offset, *arm11Section1 = (u8 *)firm + firm->section[1].offset; @@ -161,7 +161,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo ret += reimplementSvcBackdoor(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space); } - ret += implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space); + ret += implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, baseK11VA, &freeK11Space, isSafeMode); //Apply UNITINFO patch if(devMode == 2) ret += patchUnitInfoValueSet(arm9Section, kernel9Size); diff --git a/source/firm.h b/source/firm.h index 9970236..89ae31b 100644 --- a/source/firm.h +++ b/source/firm.h @@ -24,8 +24,8 @@ #include "types.h" -u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage); -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lhInstalled, u32 devMode); +u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode); +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lhInstalled, bool isSafeMode, u32 devMode); u32 patchTwlFirm(u32 firmVersion, u32 devMode); u32 patchAgbFirm(u32 devMode); u32 patch1x2xNativeAndSafeFirm(u32 devMode); diff --git a/source/main.c b/source/main.c index 41a2ad7..92ddd73 100644 --- a/source/main.c +++ b/source/main.c @@ -36,7 +36,8 @@ extern FirmwareSource firmSource; void main(void) { - bool isA9lhInstalled; + bool isA9lhInstalled, + isSafeMode = false; u32 configTemp, emuHeader; FirmwareType firmType; @@ -83,7 +84,7 @@ void main(void) u32 pressed = HID_PAD; //Save old options and begin saving the new boot configuration - configTemp = (configData.config & 0xFFFFFE00) | ((u32)ISA9LH << 6); + configTemp = (configData.config & 0xFFFFFF00) | ((u32)ISA9LH << 6); //If it's a MCU reboot, try to force boot options if(ISA9LH && CFG_BOOTENV && needConfig != CREATE_CONFIGURATION) @@ -131,8 +132,7 @@ void main(void) nandType = FIRMWARE_SYSNAND; firmSource = FIRMWARE_SYSNAND; - //Flag to tell loader to init SD - configTemp |= 1 << 8; + isSafeMode = true; //If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo if(pinExists && !shouldLoadConfigMenu) @@ -228,7 +228,7 @@ void main(void) if(isSdMode && !mountFs(false, false)) error("Failed to mount CTRNAND."); bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES); - u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage); + u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode); u32 devMode = MULTICONFIG(DEVOPTIONS); @@ -236,7 +236,7 @@ void main(void) switch(firmType) { case NATIVE_FIRM: - res = patchNativeFirm(firmVersion, nandType, emuHeader, isA9lhInstalled, devMode); + res = patchNativeFirm(firmVersion, nandType, emuHeader, isA9lhInstalled, isSafeMode, devMode); break; case SAFE_FIRM: case NATIVE_FIRM1X2X: diff --git a/source/patches.c b/source/patches.c index d60124f..f406b67 100644 --- a/source/patches.c +++ b/source/patches.c @@ -237,7 +237,7 @@ u32 reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **free return ret; } -u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space) +u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space, bool isSafeMode) { u32 ret; @@ -249,7 +249,7 @@ u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **free struct CfwInfo { char magic[4]; - + u8 versionMajor; u8 versionMinor; u8 versionBuild; @@ -278,6 +278,10 @@ u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **free if(isRelease) info->flags = 1; + if(ISN3DS) info->flags |= 1 << 4; + + if(isSafeMode) info->flags |= 1 << 5; + arm11SvcTable[0x2E] = baseK11VA + *freeK11Space - pos; //Stubbed svc *freeK11Space += svcGetCFWInfo_bin_size; diff --git a/source/patches.h b/source/patches.h index ebb0868..299bdc4 100644 --- a/source/patches.h +++ b/source/patches.h @@ -42,7 +42,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); u32 patchFirmWrites(u8 *pos, u32 size); u32 patchOldFirmWrites(u8 *pos, u32 size); u32 reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space); -u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space); +u32 implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space, bool isSafeMode); u32 patchArm9ExceptionHandlersInstall(u8 *pos, u32 size); u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset); u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address);