diff --git a/Makefile b/Makefile index 66ad4fe..e6f2100 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,15 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/injector.h \ - $(dir_build)/loader.h $(dir_build)/k11modulespatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h +bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/svcGetCFWInfopatch.h $(dir_build)/injector.h $(dir_build)/loader.h + +ifeq ($(strip $(BUILD)),DEV) +CFLAGS += -DDEV +bundled += $(dir_build)/k11modulespatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h +title := \"$(name) $(revision) (dev) configuration\" +else +title := \"$(name) $(revision) configuration\" +endif .PHONY: all all: launcher a9lh ninjhax @@ -109,7 +116,7 @@ $(dir_build)/svcGetCFWInfopatch.h: $(dir_patches)/svcGetCFWInfo.s $(dir_build)/injector.h: $(dir_injector)/Makefile @mkdir -p "$(@D)" - @$(MAKE) -C $(dir_injector) + @$(MAKE) -C $(dir_injector) BUILD=$(BUILD) @bin2c -o $@ -n injector $(@D)/injector.cxi $(dir_build)/loader.h: $(dir_loader)/Makefile @@ -125,7 +132,7 @@ $(dir_build)/arm11_exceptions.h: $(dir_arm11_exceptions)/Makefile @bin2c -o $@ -n arm11_exceptions $(@D)/arm11_exceptions.bin $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 -$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) (dev) configuration\"" +$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="$(title)" $(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)" $(dir_build)/%.o: $(dir_source)/%.c $(bundled) diff --git a/injector/Makefile b/injector/Makefile index e733480..36f34bd 100755 --- a/injector/Makefile +++ b/injector/Makefile @@ -30,6 +30,10 @@ LDFLAGS := -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ASFLAGS) objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c)) +ifeq ($(strip $(BUILD)),DEV) +CFLAGS += -DDEV +endif + .PHONY: all all: ../$(dir_build)/$(name).cxi diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 03e36bf..95c5a97 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -495,6 +495,7 @@ void patchCode(u64 progId, u8 *code, u32 size) break; } +#ifdef DEV case 0x0004003000008A02LL: // ErrDisp { if(CONFIG_DEVOPTIONS == 0) @@ -528,6 +529,7 @@ void patchCode(u64 progId, u8 *code, u32 size) break; } +#endif default: if(CONFIG_USELANGEMUANDCODE) diff --git a/source/config.c b/source/config.c index 18df697..0c049d0 100644 --- a/source/config.c +++ b/source/config.c @@ -74,16 +74,22 @@ void configMenu(bool oldPinStatus) const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )", "Screen brightness: 4( ) 3( ) 2( ) 1( )", "PIN lock: Off( ) 4( ) 6( ) 8( ) digits", - "New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )", - "Dev. features: ErrDisp( ) UNITINFO( ) None( )" }; + "New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )" +#ifdef DEV + , "Dev. features: ErrDisp( ) UNITINFO( ) None( )" +#endif + }; const char *singleOptionsText[] = { "( ) Autoboot SysNAND", "( ) Use SysNAND FIRM if booting with R (A9LH)", "( ) Enable region/language emu. and ext. .code", "( ) Show current NAND in System Settings", "( ) Show GBA boot screen in patched AGB_FIRM", - "( ) Display splash screen before payloads", - "( ) Patch SVC/service/archive/ARM9 access" }; + "( ) Display splash screen before payloads" +#ifdef DEV + , "( ) Patch SVC/service/archive/ARM9 access" +#endif + }; struct multiOption { int posXs[4]; @@ -93,8 +99,10 @@ void configMenu(bool oldPinStatus) { .posXs = {19, 24, 29, 34} }, { .posXs = {21, 26, 31, 36} }, { .posXs = {14, 19, 24, 29} }, - { .posXs = {17, 26, 32, 44} }, - { .posXs = {23, 35, 43, 0} } + { .posXs = {17, 26, 32, 44} } +#ifdef DEV + , { .posXs = {23, 35, 43, 0} } +#endif }; //Calculate the amount of the various kinds of options and pre-select the first single one diff --git a/source/config.h b/source/config.h index 3247140..c57414b 100644 --- a/source/config.h +++ b/source/config.h @@ -40,12 +40,15 @@ #define CONFIG_DEFAULTEMU MULTICONFIG(0) #define CONFIG_BRIGHTNESS MULTICONFIG(1) #define CONFIG_PIN MULTICONFIG(2) -#define CONFIG_DEVOPTIONS MULTICONFIG(4) #define CONFIG_AUTOBOOTSYS CONFIG(0) #define CONFIG_USESYSFIRM CONFIG(1) #define CONFIG_SHOWGBABOOT CONFIG(4) #define CONFIG_PAYLOADSPLASH CONFIG(5) + +#ifdef DEV +#define CONFIG_DEVOPTIONS MULTICONFIG(4) #define CONFIG_PATCHACCESS CONFIG(6) +#endif typedef struct __attribute__((packed)) { diff --git a/source/exceptions.c b/source/exceptions.c index 55f6ba0..dfdfe96 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -20,6 +20,7 @@ * Notices displayed by works containing it. */ +#ifdef DEV #include "exceptions.h" #include "fs.h" #include "strings.h" @@ -186,4 +187,5 @@ void detectAndProcessExceptionDumps(void) waitInput(); mcuPowerOff(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/source/exceptions.h b/source/exceptions.h index 27e8a69..4eb8a6c 100644 --- a/source/exceptions.h +++ b/source/exceptions.h @@ -20,6 +20,7 @@ * Notices displayed by works containing it. */ +#ifdef DEV #pragma once #include "types.h" @@ -44,4 +45,5 @@ typedef struct __attribute__((packed)) void installArm9Handlers(void); void installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset); -void detectAndProcessExceptionDumps(void); \ No newline at end of file +void detectAndProcessExceptionDumps(void); +#endif \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index d4da54f..59c8bdc 100755 --- a/source/firm.c +++ b/source/firm.c @@ -30,13 +30,16 @@ #include "cache.h" #include "emunand.h" #include "crypto.h" -#include "exceptions.h" #include "draw.h" #include "screen.h" #include "buttons.h" #include "pin.h" #include "../build/injector.h" +#ifdef DEV +#include "exceptions.h" +#endif + extern u16 launchedFirmTidLow[8]; //Defined in start.s static firmHeader *const firm = (firmHeader *)0x24000000; @@ -70,7 +73,9 @@ void main(void) //Attempt to read the configuration file needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; +#ifdef DEV detectAndProcessExceptionDumps(); +#endif //Determine if this is a firmlaunch boot if(launchedFirmTidLow[5] != 0) @@ -86,7 +91,9 @@ void main(void) firmSource = (FirmwareSource)BOOTCFG_FIRM; isA9lh = BOOTCFG_A9LH != 0; +#ifdef DEV if(isA9lh) installArm9Handlers(); +#endif } else { @@ -96,7 +103,9 @@ void main(void) //Determine if booting with A9LH isA9lh = !PDN_SPI_CNT; +#ifdef DEV if(isA9lh) installArm9Handlers(); +#endif //Get pressed buttons u32 pressed = HID_PAD; @@ -250,6 +259,7 @@ void main(void) launchFirm(firmType); } +#ifdef DEV static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) { section = firm->section; @@ -294,6 +304,43 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) return firmVersion; } +#else +static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) +{ + section = firm->section; + + //Load FIRM from CTRNAND + u32 firmVersion = firmRead(firm, (u32)*firmType); + + if(!isN3DS && *firmType == NATIVE_FIRM) + { + if(firmVersion < 0x18) + { + //We can't boot < 3.x EmuNANDs + if(firmSource != 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"); + + *firmType = NATIVE_FIRM1X2X; + } + + //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD + else if(firmVersion < 0x25) + { + if(!fileRead(firm, "/luma/firmware.bin") || section[2].address != (u8 *)0x8006800) + error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot"); + + //No assumption regarding FIRM version + firmVersion = 0xFFFFFFFF; + } + } + + if(firmVersion != 0xFFFFFFFF) decryptExeFs((u8 *)firm); + + return firmVersion; +} +#endif static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh) { @@ -315,11 +362,17 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); +#ifdef DEV //Find Kernel11 SVC table and handler, exceptions page and free space locations u8 *freeK11Space; u32 *arm11SvcHandler, *arm11ExceptionsPage, *arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage); +#else + //Find Kernel11 SVC table and free space locations + u8 *freeK11Space; + u32 *arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &freeK11Space); +#endif //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -349,6 +402,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, &freeK11Space); +#ifdef DEV //Apply UNITINFO patch if(CONFIG_DEVOPTIONS == 1) patchUnitInfoValueSet(arm9Section, section[2].size); @@ -377,6 +431,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 patchK11ModuleChecks(arm11Section1, section[1].size, &freeK11Space); patchP9AccessChecks(process9Offset, process9Size); } +#endif } static inline void patchLegacyFirm(FirmwareType firmType) @@ -390,10 +445,12 @@ static inline void patchLegacyFirm(FirmwareType firmType) firm->arm9Entry = (u8 *)0x801301C; } + applyLegacyFirmPatches((u8 *)firm, firmType); + +#ifdef DEV //Apply UNITINFO patch if(CONFIG_DEVOPTIONS == 1) patchUnitInfoValueSet(arm9Section, section[3].size); - - applyLegacyFirmPatches((u8 *)firm, firmType); +#endif } static inline void patch1x2xNativeAndSafeFirm(void) @@ -410,14 +467,17 @@ static inline void patch1x2xNativeAndSafeFirm(void) } else patchOldFirmWrites(arm9Section, section[2].size); +#ifdef DEV if(CONFIG_DEVOPTIONS != 2) { //Kernel9/Process9 debugging patchArm9ExceptionHandlersInstall(arm9Section, section[2].size); patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address); } +#endif } +#ifdef DEV static inline void copySection0AndInjectSystemModules(FirmwareType firmType) { u32 srcModuleSize, @@ -457,14 +517,51 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType) } } } +#else +static inline void copySection0AndInjectSystemModules(void) +{ + u32 srcModuleSize, + dstModuleSize; + + for(u8 *src = (u8 *)firm + section[0].offset, *srcEnd = src + section[0].size, *dst = section[0].address; + src < srcEnd; src += srcModuleSize, dst += dstModuleSize) + { + srcModuleSize = *(u32 *)(src + 0x104) * 0x200; + char *moduleName = (char *)(src + 0x200); + + void *module; + + if(memcmp(moduleName, "loader", 6) == 0) + { + module = (void *)injector; + dstModuleSize = injector_size; + } + else + { + module = src; + dstModuleSize = srcModuleSize; + } + + memcpy(dst, module, dstModuleSize); + } +} +#endif static inline void launchFirm(FirmwareType firmType) { +#ifdef DEV //Allow module injection and/or inject 3ds_injector on new NATIVE_FIRMs and LGY FIRMs u32 sectionNum; if(firmType != SAFE_FIRM && firmType != NATIVE_FIRM1X2X) { copySection0AndInjectSystemModules(firmType); +#else + //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector + u32 sectionNum; + if(firmType == NATIVE_FIRM) + { + copySection0AndInjectSystemModules(); +#endif sectionNum = 1; } else sectionNum = 0; diff --git a/source/firm.h b/source/firm.h index 655fe9c..a8f0b4e 100644 --- a/source/firm.h +++ b/source/firm.h @@ -51,5 +51,9 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource); static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patch1x2xNativeAndSafeFirm(void); +#ifdef DEV static inline void copySection0AndInjectSystemModules(FirmwareType firmType); +#else +static inline void copySection0AndInjectSystemModules(void); +#endif static inline void launchFirm(FirmwareType firmType); \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index 94d4269..43a8ac6 100644 --- a/source/fs.c +++ b/source/fs.c @@ -192,6 +192,7 @@ u32 firmRead(void *dest, u32 firmType) return firmVersion; } +#ifdef DEV void findDumpFile(const char *path, char *fileName) { DIR dir; @@ -203,7 +204,7 @@ void findDumpFile(const char *path, char *fileName) u32 i = 18, tmp = ++n; - while(tmp) + while(tmp > 0) { fileName[i--] = '0' + (tmp % 10); tmp /= 10; @@ -211,4 +212,5 @@ void findDumpFile(const char *path, char *fileName) } f_closedir(&dir); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/source/fs.h b/source/fs.h index c7e3d43..61c9f1b 100644 --- a/source/fs.h +++ b/source/fs.h @@ -36,4 +36,6 @@ void fileDelete(const char *path); void loadPayload(u32 pressed); u32 firmRead(void *dest, u32 firmType); +#ifdef DEV void findDumpFile(const char *path, char *fileName); +#endif \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index a36f456..41c8fa7 100644 --- a/source/patches.c +++ b/source/patches.c @@ -25,7 +25,10 @@ #include "config.h" #include "../build/rebootpatch.h" #include "../build/svcGetCFWInfopatch.h" + +#ifdef DEV #include "../build/k11modulespatch.h" +#endif u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { @@ -38,6 +41,7 @@ u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; } +#ifdef DEV u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage) { const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; @@ -54,6 +58,23 @@ u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space, u32 **arm11SvcHandler return arm11SvcTable; } +#else +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space) +{ + const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; + + u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, sizeof(pattern)) - 0xB; + u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch + u32 *arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address + while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) + + const u8 pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + *freeK11Space = memsearch(pos, pattern2, size, sizeof(pattern2)) + 1; + + return arm11SvcTable; +} +#endif void patchSignatureChecks(u8 *pos, u32 size) { @@ -155,7 +176,12 @@ void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space) } else isRelease = rev[4] == 0; - info->flags = 1 /* dev branch */ | ((isRelease ? 1 : 0) << 1) /* is release */; +#ifdef DEV + info->flags = 1 /* dev branch */ | +#else + info->flags = 0 /* master branch */ | +#endif + ((isRelease ? 1 : 0) << 1) /* is release */; arm11SvcTable[0x2E] = 0xFFF00000 + *freeK11Space - pos; //Stubbed svc *freeK11Space += svcGetCFWInfo_size; @@ -211,6 +237,7 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType) } } +#ifdef DEV void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size) { const u8 pattern[] = {0x03, 0xA0, 0xE3, 0x18}; @@ -337,4 +364,5 @@ void patchUnitInfoValueSet(u8 *pos, u32 size) off[0] = isDevUnit ? 0 : 1; off[3] = 0xE3; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/source/patches.h b/source/patches.h index f8c5f53..6847f82 100644 --- a/source/patches.h +++ b/source/patches.h @@ -50,7 +50,6 @@ typedef struct __attribute__((packed)) extern bool isN3DS, isDevUnit; u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); -u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); @@ -60,6 +59,8 @@ void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); +#ifdef DEV +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size); u32 getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *codeSetOffset); void patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address); @@ -69,4 +70,7 @@ void patchKernel11Panic(u8 *pos, u32 size); void patchP9AccessChecks(u8 *pos, u32 size); void patchArm11SvcAccessChecks(u32 *arm11SvcHandler); void patchK11ModuleChecks(u8 *pos, u32 size, u8 **freeK11Space); -void patchUnitInfoValueSet(u8 *pos, u32 size); \ No newline at end of file +void patchUnitInfoValueSet(u8 *pos, u32 size); +#else +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space); +#endif \ No newline at end of file