diff --git a/arm9/source/config.c b/arm9/source/config.c index 02276b4..fcac6c5 100644 --- a/arm9/source/config.c +++ b/arm9/source/config.c @@ -95,6 +95,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Set developer UNITINFO", "( ) Disable Arm11 exception handlers", + "( ) Enable Rosalina on SAFE_FIRM", }; static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n" @@ -193,7 +194,16 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "Note: Disabling the exception handlers\n" "will disqualify you from submitting\n" "issues or bug reports to the Luma3DS\n" - "GitHub repository!" + "GitHub repository!", + + "Enables Rosalina, the kernel ext.\n" + "and sysmodule reimplementations on\n" + "SAFE_FIRM (New 3DS only).\n\n" + "Also suppresses QTM error 0xF96183FE,\n" + "allowing to use 8.1-11.3 N3DS on\n" + "New 2DS XL consoles.\n\n" + "Only select this if you know what you\n" + "are doing!", }; FirmwareSource nandType = FIRMWARE_SYSNAND; @@ -229,7 +239,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) { .visible = true }, { .visible = true }, { .visible = true }, - { .visible = true } + { .visible = true }, + { .visible = ISN3DS }, }; //Calculate the amount of the various kinds of options and pre-select the first single one diff --git a/arm9/source/config.h b/arm9/source/config.h index 78514e1..de81062 100644 --- a/arm9/source/config.h +++ b/arm9/source/config.h @@ -34,7 +34,7 @@ #define CONFIG_FILE "config.bin" #define CONFIG_VERSIONMAJOR 2 -#define CONFIG_VERSIONMINOR 3 +#define CONFIG_VERSIONMINOR 4 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) @@ -60,7 +60,8 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; typedef enum ConfigurationStatus diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 22de414..ea620fc 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -278,7 +278,8 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200; } - if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D)) + // SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on + if((firmType == NATIVE_FIRM || firmType == SAFE_FIRM) && (ISN3DS || firmVersion >= 0x1D)) { //2) Merge that info with our own modules' for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize) @@ -303,7 +304,9 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo //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 = firmType == NATIVE_FIRM ? 0x80000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize) + // SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on + u32 maxModuleSize = (firmType == NATIVE_FIRM || firmType == SAFE_FIRM) ? 0x80000 : 0x600000; + for(u32 i = 0, dstModuleSize; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize) { if(loadFromStorage) { @@ -335,7 +338,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo memcpy(dst, moduleList[i].src, dstModuleSize); } - //4) Patch NATIVE_FIRM if necessary + //4) Patch NATIVE_FIRM/SAFE_FIRM (N3DS) if necessary if(nbModules == 6) { if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0) @@ -522,6 +525,31 @@ u32 patch1x2xNativeAndSafeFirm(void) ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size); ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address); + if(ISN3DS && CONFIG(ENABLESAFEFIRMROSALINA)) + { + u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset; + //Find the Kernel11 SVC table and handler, exceptions page and free space locations + u32 baseK11VA; + u8 *freeK11Space; + u32 *arm11SvcHandler, + *arm11ExceptionsPage, + *arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage); + + ret += installK11Extension(arm11Section1, firm->section[1].size, false, baseK11VA, arm11ExceptionsPage, &freeK11Space); + ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage); + + // Add some other patches to the mix, as we can now launch homebrew on SAFE_FIRM: + + //Apply firmlaunch patches + ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + + ret += patchKernel9Panic(arm9Section, kernel9Size); + ret += patchP9AccessChecks(process9Offset, process9Size); + + mergeSection0(NATIVE_FIRM, 0x45, false); // may change in the future + firm->section[0].size = 0; + } + return ret; } diff --git a/k11_extension/include/config.h b/k11_extension/include/config.h index 5193cc2..1970796 100644 --- a/k11_extension/include/config.h +++ b/k11_extension/include/config.h @@ -33,5 +33,6 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; diff --git a/k11_extension/source/ipc.c b/k11_extension/source/ipc.c index 5dfeb63..74a5d72 100644 --- a/k11_extension/source/ipc.c +++ b/k11_extension/source/ipc.c @@ -246,24 +246,24 @@ bool doErrfThrowHook(u32 *cmdbuf) u8 *srcerrbuf = (u8 *)r0_to_r7_r12_usr[(spsr & 0x20) ? 4 : 6]; const char *pname = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->processName; - static const struct + const struct { const char *name; Result errCode; + bool enabled; } errorCodesToIgnore[] = { /* - If you're getting this error, you have broken your head-tracking hardware, - and should uncomment the following line: + If you're getting this error, you may have broken your head-tracking hardware, + and you need to enable the qtm error bypass below: */ - //{ "qtm", (Result)0xF96183FE }, - - { "", 0 }, // impossible case to ensure the array has at least 1 element + { "qtm", 0xF96183FEu, CONFIG(ENABLESAFEFIRMROSALINA)}, + { "", 0, false}, // impossible case to ensure the array has at least 1 element }; for(u32 i = 0; i < sizeof(errorCodesToIgnore) / sizeof(errorCodesToIgnore[0]); i++) { - if(strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode) + if(errorCodesToIgnore[i].enabled && strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode) { srcerrbuf[0] = 5; cmdbuf[0] = 0x10040; diff --git a/sysmodules/loader/source/patcher.h b/sysmodules/loader/source/patcher.h index 7acb9ba..afc1507 100644 --- a/sysmodules/loader/source/patcher.h +++ b/sysmodules/loader/source/patcher.h @@ -35,7 +35,8 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; extern u32 config, multiConfig, bootConfig;