diff --git a/Makefile b/Makefile index e780988..70bf2f9 100644 --- a/Makefile +++ b/Makefile @@ -106,7 +106,6 @@ $(dir_build)/loader.h: $(dir_loader)/Makefile $(dir_build)/arm9_exceptions.h: $(dir_arm9_exceptions)/Makefile @$(MAKE) -C $(dir_arm9_exceptions) - @mv $(dir_arm9_exceptions)/arm9_exceptions.bin $(@D) @bin2c -o $@ -n arm9_exceptions $(@D)/arm9_exceptions.bin $(dir_build)/screeninit.h: $(dir_screeninit)/Makefile @@ -114,7 +113,7 @@ $(dir_build)/screeninit.h: $(dir_screeninit)/Makefile @bin2c -o $@ -n screeninit $(@D)/screeninit.bin $(dir_build)/memory.o: CFLAGS += -O3 -$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\"" +$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) (dev) configuration\"" $(dir_build)/%.o: $(dir_source)/%.c $(bundled) @mkdir -p "$(@D)" diff --git a/exceptions/arm9/Makefile b/exceptions/arm9/Makefile index de8f9b2..f0a0f33 100644 --- a/exceptions/arm9/Makefile +++ b/exceptions/arm9/Makefile @@ -25,13 +25,13 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) .PHONY: all -all: $(name).bin +all: ../../$(dir_build)/$(name).bin .PHONY: clean clean: @rm -rf $(dir_build) -$(name).bin: $(dir_build)/$(name).elf +../../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf $(OC) -S -O binary $< $@ $(dir_build)/$(name).elf: $(objects) diff --git a/source/firm.c b/source/firm.c index ae35183..1d6420b 100755 --- a/source/firm.c +++ b/source/firm.c @@ -24,41 +24,6 @@ u32 config, firmSource, emuOffset; -static inline void patchExceptionHandlersInstall(u8 *arm9Section) -{ - static const u8 pattern[] = { - 0x18, 0x10, 0x80, 0xE5, - 0x10, 0x10, 0x80, 0xE5, - 0x20, 0x10, 0x80, 0xE5, - 0x28, 0x10, 0x80, 0xE5, - }; //i.e when it stores ldr pc, [pc, #-4] - - u32* off = (u32 *)(memsearch(arm9Section, pattern, section[2].size, sizeof(pattern))); - if(off == NULL) return; - off += sizeof(pattern)/4; - - u32 r0 = 0x08000000; - - for(; *off != 0xE3A01040; off++) //until mov r1, #0x40 - { - if((*off >> 26) != 0x39 || ((*off >> 16) & 0xf) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0) - continue; //discard everything that's not str rX, [r0, #imm](!) - - int rD = (*off >> 12) & 0xf; - int offset = (*off & 0xfff) * ((((*off >> 23) & 1) == 0) ? -1 : 1); - int writeback = (*off >> 21) & 1, pre = (*off >> 24) & 1; - - u32 addr = r0 + ((pre || !writeback) ? offset : 0); - if(addr != 0x08000014 && addr != 0x08000004) - *off = 0xE1A00000; //nop - else - *off = 0xE5800000 | (rD << 12) | (addr & 0xfff); //preserve IRQ and svc handlers - - if(!pre) addr += offset; - if(writeback) r0 = addr; - } -} - void main(void) { u32 bootType, @@ -247,7 +212,7 @@ void main(void) loadFirm(firmType, !firmType && updatedSys == !firmSource); - patchExceptionHandlersInstall((u8 *)firm + section[2].offset); + patchExceptionHandlersInstall((u8 *)firm + section[2].offset, section[2].size); switch(firmType) { @@ -293,21 +258,6 @@ static inline void loadFirm(u32 firmType, u32 externalFirm) } } -static inline void patchKernelFCRAMAndVRAMMappingPermissions(void) -{ - static const u8 MMUConfigPattern[] = { - 0xC4, 0xDD, 0xFA, 0x1F, - 0x16, 0x64, 0x01, 0x00, - 0xBC, 0xDD, 0xFA, 0x1F, - 0x00, 0x50, 0xFF, 0x1F - }; - - u8 *arm11Section1 = (u8 *)firm + section[1].offset; - - u32* off = (u32 *)memsearch(arm11Section1, MMUConfigPattern, section[1].size, sizeof(MMUConfigPattern)); - if(off != NULL) off[1] &= ~(1 << 4); //clear XN bit -} - static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) { u8 *arm9Section = (u8 *)firm + section[2].offset; @@ -367,16 +317,14 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) //Does nothing if svcBackdoor is still there if(nativeFirmType == 1) reimplementSvcBackdoor((u8 *)firm + section[1].offset, section[1].size); - if(nativeFirmType == 1) reimplementSvcBackdoor(); if(DEVMODE) { //Apply UNITINFO patch - u8 *unitInfoOffset = getUnitInfoValueSet(arm9Section, section[2].size); - *unitInfoOffset = unitInfoPatch; + patchUnitInfoValueSet(arm9Section, section[2].size); //Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel - patchKernelFCRAMAndVRAMMappingPermissions(); + patchKernelFCRAMAndVRAMMappingPermissions(arm9Section, section[2].size); } } diff --git a/source/firm.h b/source/firm.h index 8e3098b..3115edc 100644 --- a/source/firm.h +++ b/source/firm.h @@ -29,7 +29,6 @@ typedef struct firmHeader { } firmHeader; static inline void loadFirm(u32 firmType, u32 externalFirm); -static inline void patchKernelFCRAMAndVRAMMappingPermissions(void); static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode); static inline void patchLegacyFirm(u32 firmType); static inline void patchSafeFirm(void); diff --git a/source/patches.c b/source/patches.c index b412f48..32e3a4b 100644 --- a/source/patches.c +++ b/source/patches.c @@ -7,8 +7,6 @@ #include "config.h" #include "../build/rebootpatch.h" -const u8 unitInfoPatch = 0xE3; - u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { u8 *off = memsearch(pos, "ess9", size, 4); @@ -90,12 +88,61 @@ void patchFirmWriteSafe(u8 *pos, u32 size) off[1] = writeBlockSafe[1]; } -u8 *getUnitInfoValueSet(u8 *pos, u32 size) +void patchExceptionHandlersInstall(u8 *pos, u32 size) +{ + static const u8 pattern[] = { + 0x18, 0x10, 0x80, 0xE5, + 0x10, 0x10, 0x80, 0xE5, + 0x20, 0x10, 0x80, 0xE5, + 0x28, 0x10, 0x80, 0xE5, + }; //i.e when it stores ldr pc, [pc, #-4] + + u32* off = (u32 *)(memsearch(pos, pattern, size, sizeof(pattern))); + if(off == NULL) return; + off += sizeof(pattern)/4; + + u32 r0 = 0x08000000; + + for(; *off != 0xE3A01040; off++) //until mov r1, #0x40 + { + if((*off >> 26) != 0x39 || ((*off >> 16) & 0xf) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0) + continue; //discard everything that's not str rX, [r0, #imm](!) + + int rD = (*off >> 12) & 0xf; + int offset = (*off & 0xfff) * ((((*off >> 23) & 1) == 0) ? -1 : 1); + int writeback = (*off >> 21) & 1, pre = (*off >> 24) & 1; + + u32 addr = r0 + ((pre || !writeback) ? offset : 0); + if(addr != 0x08000014 && addr != 0x08000004) + *off = 0xE1A00000; //nop + else + *off = 0xE5800000 | (rD << 12) | (addr & 0xfff); //preserve IRQ and svc handlers + + if(!pre) addr += offset; + if(writeback) r0 = addr; + } +} + +void patchUnitInfoValueSet(u8 *pos, u32 size) { //Look for UNITINFO value being set const u8 pattern[] = {0x01, 0x10, 0xA0, 0x13}; - return memsearch(pos, pattern, size, 4) + 3; + u8 *off = memsearch(pos, pattern, size, 4); + if(off != NULL) off[3] = 0xE3; +} + +void patchKernelFCRAMAndVRAMMappingPermissions(u8 *pos, u32 size) +{ + static const u8 MMUConfigPattern[] = { + 0xC4, 0xDD, 0xFA, 0x1F, + 0x16, 0x64, 0x01, 0x00, + 0xBC, 0xDD, 0xFA, 0x1F, + 0x00, 0x50, 0xFF, 0x1F + }; + + u32* off = (u32 *)memsearch(pos, MMUConfigPattern, size, sizeof(MMUConfigPattern)); + if(off != NULL) off[1] &= ~(1 << 4); //clear XN bit } void reimplementSvcBackdoor(u8 *pos, u32 size) diff --git a/source/patches.h b/source/patches.h index 07041ab..35e4dac 100644 --- a/source/patches.h +++ b/source/patches.h @@ -14,13 +14,17 @@ typedef struct patchData { } patch; u32 type; } patchData; -const u8 unitInfoPatch; + u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); void patchFirmWriteSafe(u8 *pos, u32 size); +void patchExceptionHandlersInstall(u8 *pos, u32 size); +void patchUnitInfoValueSet(u8 *pos, u32 size); +void patchKernelFCRAMAndVRAMMappingPermissions(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void applyLegacyFirmPatches(u8 *pos, u32 firmType, u32 console); +u32 getLoader(u8 *pos, u32 *loaderSize); u8 *getUnitInfoValueSet(u8 *pos, u32 size); \ No newline at end of file