diff --git a/Makefile b/Makefile index bc396f8..a100954 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ dir_source := source dir_patches := patches dir_loader := loader dir_arm9_exceptions := exceptions/arm9 +dir_arm11_exceptions := exceptions/arm11 dir_screeninit := screeninit dir_injector := injector dir_mset := CakeHax @@ -34,7 +35,7 @@ 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)/arm9_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h $(dir_build)/screeninit.h +bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/arm9_exceptions.h $(dir_build)/arm11_exceptions.h $(dir_build)/injector.h $(dir_build)/loader.h $(dir_build)/screeninit.h .PHONY: all all: launcher a9lh ninjhax @@ -56,6 +57,7 @@ clean: @$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean @$(MAKE) -C $(dir_loader) clean @$(MAKE) -C $(dir_arm9_exceptions) clean + @$(MAKE) -C $(dir_arm11_exceptions) clean @$(MAKE) -C $(dir_screeninit) clean @$(MAKE) -C $(dir_injector) clean @rm -rf $(dir_out) $(dir_build) @@ -63,6 +65,7 @@ clean: $(dir_out): @mkdir -p "$(dir_out)/luma/payloads" @mkdir -p "$(dir_out)/luma/dumps/arm9" + @mkdir -p "$(dir_out)/luma/dumps/arm11" $(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out) @$(MAKE) $(FLAGS) -C $(dir_mset) launcher @@ -108,6 +111,10 @@ $(dir_build)/arm9_exceptions.h: $(dir_arm9_exceptions)/Makefile @$(MAKE) -C $(dir_arm9_exceptions) @bin2c -o $@ -n arm9_exceptions $(@D)/arm9_exceptions.bin +$(dir_build)/arm11_exceptions.h: $(dir_arm11_exceptions)/Makefile + @$(MAKE) -C $(dir_arm11_exceptions) + @bin2c -o $@ -n arm11_exceptions $(@D)/arm11_exceptions.bin + $(dir_build)/screeninit.h: $(dir_screeninit)/Makefile @$(MAKE) -C $(dir_screeninit) @bin2c -o $@ -n screeninit $(@D)/screeninit.bin diff --git a/exceptions/arm11/Makefile b/exceptions/arm11/Makefile new file mode 100644 index 0000000..428f7c5 --- /dev/null +++ b/exceptions/arm11/Makefile @@ -0,0 +1,47 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/3ds_rules + +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +LD := arm-none-eabi-ld +OC := arm-none-eabi-objcopy + +name := arm11_exceptions + +dir_source := source +dir_build := build + +ASFLAGS := -mcpu=mpcore -mfpu=vfp +CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math +LDFLAGS := -nostdlib + +objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ + $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ + $(call rwildcard, $(dir_source), *.s *.c))) + +.PHONY: all +all: ../../$(dir_build)/$(name).bin + +.PHONY: clean +clean: + @rm -rf $(dir_build) + +../../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf + $(OC) -S -O binary $< $@ + +$(dir_build)/$(name).elf: $(objects) + $(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^ + +$(dir_build)/%.o: $(dir_source)/%.c + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.s) $(OUTPUT_OPTION) $< +include $(call rwildcard, $(dir_build), *.d) diff --git a/exceptions/arm11/linker.ld b/exceptions/arm11/linker.ld new file mode 100644 index 0000000..fbaa849 --- /dev/null +++ b/exceptions/arm11/linker.ld @@ -0,0 +1,11 @@ +ENTRY(_start) +SECTIONS +{ + . = 0; + .text.start : { *(.text.start) } + .text : { *(.text) } + .data : { *(.data) } + .bss : { *(.bss COMMON) } + .rodata : { *(.rodata) } + . = ALIGN(4); +} diff --git a/exceptions/arm11/source/handlers.h b/exceptions/arm11/source/handlers.h new file mode 100644 index 0000000..33da59b --- /dev/null +++ b/exceptions/arm11/source/handlers.h @@ -0,0 +1,14 @@ +/* +* handlers.h +* by TuxSH +* +* This is part of Luma3DS, see LICENSE.txt for details +*/ + +#pragma once + +void __attribute__((noreturn)) mcuReboot(void); +void FIQHandler(void); +void undefinedInstructionHandler(void); +void dataAbortHandler(void); +void prefetchAbortHandler(void); \ No newline at end of file diff --git a/exceptions/arm11/source/handlers.s b/exceptions/arm11/source/handlers.s new file mode 100644 index 0000000..6378b03 --- /dev/null +++ b/exceptions/arm11/source/handlers.s @@ -0,0 +1,95 @@ +@ +@ handlers.s +@ by TuxSH +@ +@ This is part of Luma3DS, see LICENSE.txt for details +@ + +.macro GEN_HANDLER name + .global \name + .type \name, %function + \name: + ldr sp, =#0xffff3000 + stmfd sp!, {r0-r7} + mov r1, #\@ @ macro expansion counter + b _commonHandler + + .size \name, . - \name +.endm + +.text +.arm +.align 4 + +.global _commonHandler +.type _commonHandler, %function +_commonHandler: + clrex + cpsid aif + mrs r2, spsr + mov r6, sp + mrs r3, cpsr + + ands r4, r2, #0xf @ get the mode that triggered the exception + moveq r4, #0xf @ usr => sys + bic r5, r3, #0xf + orr r5, r4 + msr cpsr_c, r5 @ change processor mode + stmfd r6!, {r8-lr} + msr cpsr_c, r3 @ restore processor mode + mov sp, r6 + vmrs r3, fpexc + + cmp r1, #1 + bne noFPUInit + tst r5, #0x20 + bne noFPUInit + + ldr r4, [lr, #-4] + lsl r4, #4 + sub r4, #0xc0000000 + cmp r4, #0x30000000 + bcs noFPUInit + tst r3, #0x40000000 + bne noFPUInit + + sub lr, #4 + srsfd sp!, #0x13 + add sp, #28 @ restore context + ldmfd sp!, {r0-r7} + cps #0x13 @ FPU init + stmfd sp, {r0-r3, r11-lr}^ + sub sp, #0x20 + bl . @ will be replaced + ldmfd sp, {r0-r3, r11-lr}^ + add sp, #0x20 + rfefd sp! + + noFPUInit: + stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later + @ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7 + + ldr r4, =#0xdfff3ffc + ldr r5, =#0xffff0014 + ldr r5, [r5] @ 0xeafffffe + mov r6, #0 + poisonLoop: + str r5, [r4, #4]! @ poison exception vectors in order to hang the other threads + add r6, #1 + cmp r6, #8 + blt poisonLoop + + mov r0, sp + mrc p15,0,r2,c0,c0,5 @ CPU ID register + + b mainHandler + +GEN_HANDLER FIQHandler +GEN_HANDLER undefinedInstructionHandler +GEN_HANDLER prefetchAbortHandler +GEN_HANDLER dataAbortHandler + +.global mcuReboot +.type mcuReboot, %function +mcuReboot: + b . @ will be replaced diff --git a/exceptions/arm11/source/mainHandler.c b/exceptions/arm11/source/mainHandler.c new file mode 100644 index 0000000..103c4db --- /dev/null +++ b/exceptions/arm11/source/mainHandler.c @@ -0,0 +1,71 @@ +/* +* mainHandler.c +* by TuxSH +* +* This is part of Luma3DS, see LICENSE.txt for details +*/ + +#include "types.h" +#include "handlers.h" + +#define FINAL_BUFFER 0xE5000000 //0x25000000 + +#define REG_DUMP_SIZE (4*18) +#define CODE_DUMP_SIZE 48 +#define STACK_DUMP_SIZE 0x2000 +#define OTHER_DATA_SIZE 0 + +void __attribute__((noreturn)) mainHandler(u32 regs[18], u32 type, u32 cpuId, u32 fpexc) +{ + u32 dump[(40 + REG_DUMP_SIZE + CODE_DUMP_SIZE) / 4]; + vu32 *final = (vu32 *)FINAL_BUFFER; + + while(final[0] == 0xDEADC0DE && final[1] == 0xDEADCAFE && ((final[3] & 0xFFFF) == 9 || (final[3] & 0xFFFF) == 11)); + + dump[0] = 0xDEADC0DE; //Magic + dump[1] = 0xDEADCAFE; //Magic + dump[2] = (1 << 16) | 0; //Dump format version number + dump[3] = ((cpuId & 0xf) << 16) | 11; //Processor + dump[4] = type; //Exception type + dump[6] = REG_DUMP_SIZE; //Register dump size (r0-r12, sp, lr, pc, cpsr, fpexc) + dump[7] = CODE_DUMP_SIZE; //Code dump size (10 ARM instructions, up to 20 Thumb instructions). + dump[8] = STACK_DUMP_SIZE; //Stack dump size + dump[9] = OTHER_DATA_SIZE; //Other data size + dump[5] = 40 + REG_DUMP_SIZE + CODE_DUMP_SIZE + STACK_DUMP_SIZE + OTHER_DATA_SIZE; //Total size + + //Dump registers + //Current order of saved regs: cpsr, pc, r8-r12, sp, lr, r0-r7 + u32 *regdump = dump + 10; + + u32 cpsr = regs[0]; + u32 pc = regs[1] - ((type < 3) ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8); + + regdump[15] = pc; + regdump[16] = cpsr; + regdump[17] = fpexc; + + for(u32 i = 0; i < 7; i++) + regdump[8 + i] = regs[2 + i]; + + for(u32 i = 0; i < 8; i++) + regdump[i] = regs[9 + i]; + + //Dump code + u16 *codedump = (u16 *)(regdump + dump[6] / 4); + u16 *instr = (u16 *)pc - dump[7] / 2 + 1; + for(u32 i = 0; i < dump[7] / 2; i++) + codedump[i] = instr[i]; + + //Dump stack in place + vu32 *sp = (vu32 *)regdump[13]; + vu32 *stackdump = (vu32 *)((vu8 *)FINAL_BUFFER + 40 + REG_DUMP_SIZE + CODE_DUMP_SIZE); + + for(u32 i = 0; i < dump[8] / 4; i++) + stackdump[i] = sp[i]; + + for(u32 i = 0; i < (40 + REG_DUMP_SIZE + CODE_DUMP_SIZE) / 4; i++) + final[i] = dump[i]; + + while(final[0] != 0xDEADC0DE); + mcuReboot(); +} diff --git a/exceptions/arm11/source/start.s b/exceptions/arm11/source/start.s new file mode 100644 index 0000000..aca435e --- /dev/null +++ b/exceptions/arm11/source/start.s @@ -0,0 +1,11 @@ +.section .text.start +.align 4 +.global _start +_start: + add pc, r0, #(handlers - .) @ Dummy instruction to prevent compiler optimizations + +handlers: + .word FIQHandler + .word undefinedInstructionHandler + .word prefetchAbortHandler + .word dataAbortHandler diff --git a/exceptions/arm11/source/types.h b/exceptions/arm11/source/types.h new file mode 100644 index 0000000..d27412b --- /dev/null +++ b/exceptions/arm11/source/types.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +//Common data types +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef volatile u8 vu8; +typedef volatile u16 vu16; +typedef volatile u32 vu32; +typedef volatile u64 vu64; \ No newline at end of file diff --git a/exceptions/exception_dump_parser.py b/exceptions/exception_dump_parser.py index 101e836..1432fab 100644 --- a/exceptions/exception_dump_parser.py +++ b/exceptions/exception_dump_parser.py @@ -67,7 +67,7 @@ def makeRegisterLine(A, rA, B, rB): return "{0:<15}{1:<20}{2:<15}{3:<20}".format(A, "{0:08x}".format(rA), B, "{0:08x}".format(rB)) handledExceptionNames = ("FIQ", "undefined instruction", "prefetch abort", "data abort") -registerNames = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr") +registerNames = tuple("r{0}".format(i) for i in range(13)) + ("sp", "lr", "pc", "cpsr", "fpexc") if __name__ == "__main__": parser = argparse.ArgumentParser(description="Parse Luma3DS exception dumps") @@ -80,23 +80,31 @@ if __name__ == "__main__": processor, exceptionType, _, _, codeDumpSize, stackDumpSize = unpack_from("<6I", data, 12) - print("Processor: ARM{0}".format(processor)) + if processor == 9: print("Processor: ARM9") + else: print("Processor: ARM11 (core {0})".format(processor >> 16)) + print("Exception type: {0}".format("unknown" if exceptionType >= len(handledExceptionNames) else handledExceptionNames[exceptionType])) - registers = unpack_from("<17I", data, 40) + registers = [] print("\nRegister dump:\n") - for i in range(0, 16, 2): - print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1])) - print("{0:<15}{1:<20}".format(registerNames[-1], "{0:08x}".format(registers[-1]))) + if processor == 9: + registers = unpack_from("<17I", data, 40) + for i in range(0, 16, 2): + print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1])) + print("{0:<15}{1:<20}".format(registerNames[-2], "{0:08x}".format(registers[-1]))) + else: + registers = unpack_from("<18I", data, 40) + for i in range(0, 18, 2): + print(makeRegisterLine(registerNames[i], registers[i], registerNames[i+1], registers[i+1])) - codeDump = data[40+4*17 : 40+4*17 + codeDumpSize] + codeDump = data[40+4*len(registers) : 40+4*len(registers) + codeDumpSize] print("\nCode dump:\n") print(hexdump(registers[15] - codeDumpSize + 2, codeDump)) # Homebrew/CFW set their stack at 0x27000000, let's detect it if 0 <= 0x27000000 - registers[13] <= stackDumpSize: stackDumpSize = 0x27000000 - registers[13] - stackOffset = 40+4*17 + codeDumpSize + stackOffset = 40+4*len(registers) + codeDumpSize stackDump = data[stackOffset : stackOffset + stackDumpSize] print("\nStack dump:\n") print(hexdump(registers[13], stackDump)) diff --git a/source/exceptions.c b/source/exceptions.c index e0be517..98a4617 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -11,6 +11,8 @@ #include "i2c.h" #include "utils.h" #include "../build/arm9_exceptions.h" +#include "../build/arm11_exceptions.h" + #define _U __attribute__((unused)) //Silence "unused parameter" warnings static void __attribute__((naked)) setupStack(_U u32 mode, _U void* SP) @@ -55,6 +57,40 @@ void installArm9Handlers(void) } } +#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) +#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) + +void installArm11Handlers(u32 *exceptionsPage, u32 stackAddr) +{ + u32 *initFPU; + for(initFPU = exceptionsPage; initFPU < (exceptionsPage + 0x400) && (initFPU[0] != 0xE59F0008 || initFPU[1] != 0xE5900000); initFPU += 1); + + u32 *mcuReboot; + for(mcuReboot = exceptionsPage; mcuReboot < (exceptionsPage + 0x400) && (mcuReboot[0] != 0xE59F4104 || mcuReboot[1] != 0xE3A0A0C2); mcuReboot += 1); + + u32 *freeSpace; + for(freeSpace = initFPU; freeSpace < (exceptionsPage + 0x400) && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF); freeSpace += 1); + //freeSpace += 4 - ((u32)(freeSpace - exceptionsPage) & 3); + memcpy(freeSpace, arm11_exceptions + 20, arm11_exceptions_size - 20); + + exceptionsPage[1] = MAKE_BRANCH(exceptionsPage + 1, (u8 *)freeSpace + *(u32 *)(arm11_exceptions + 8) - 20); //Undefined Instruction + exceptionsPage[3] = MAKE_BRANCH(exceptionsPage + 3, (u8 *)freeSpace + *(u32 *)(arm11_exceptions + 12) - 20); //Prefetch Abort + exceptionsPage[4] = MAKE_BRANCH(exceptionsPage + 4, (u8 *)freeSpace + *(u32 *)(arm11_exceptions + 16) - 20); //Data Abort + exceptionsPage[7] = MAKE_BRANCH(exceptionsPage + 7, (u8 *)freeSpace + *(u32 *)(arm11_exceptions + 4) - 20); //FIQ + + for(u32 *pos = freeSpace; pos < (u32 *)((u8 *)freeSpace + arm11_exceptions_size - 20); pos++) + { + switch(*pos) + { + case 0xFFFF3000: *pos = stackAddr; break; + case 0xEBFFFFFE: *pos = MAKE_BRANCH_LINK(pos, initFPU); break; + case 0xEAFFFFFE: *pos = MAKE_BRANCH(pos, mcuReboot); break; + case 0xE12FFF1C: pos[1] = 0xFFFF0000 + 4 * (u32)(freeSpace - exceptionsPage) + pos[1] - 20; break; // bx r12 (mainHandler) + default: break; + } + } +} + static void hexItoa(u32 n, char *out) { const char hexDigits[] = "0123456789ABCDEF"; @@ -77,29 +113,43 @@ void detectAndProcessExceptionDumps(void) const char *registerNames[] = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", - "SP", "LR", "PC", "CPSR" + "SP", "LR", "PC", "CPSR", "FPEXC" }; char hexstring[] = "00000000"; - vu32 *dump = (u32 *)0x25000000; + vu32 *dump = (vu32 *)0x25000000; - if(dump[0] == 0xDEADC0DE && dump[1] == 0xDEADCAFE && dump[3] == 9) + if(dump[0] == 0xDEADC0DE && dump[1] == 0xDEADCAFE && (dump[3] == 9 || (dump[3] & 0xFFFF) == 11)) { - char path[41] = "/luma/dumps/arm9"; + char path9[41] = "/luma/dumps/arm9"; + char path11[42] = "/luma/dumps/arm11"; char fileName[] = "crash_dump_00000000.dmp"; - findDumpFile(path, fileName); - - path[16] = '/'; - memcpy(&path[17], fileName, sizeof(fileName)); - - fileWrite((void *)dump, path, dump[5]); + if(dump[3] == 9) + { + findDumpFile(path9, fileName); + path9[16] = '/'; + memcpy(&path9[17], fileName, sizeof(fileName)); + fileWrite((void *)dump, path9, dump[5]); + } + + else + { + findDumpFile(path11, fileName); + path11[17] = '/'; + memcpy(&path11[18], fileName, sizeof(fileName)); + fileWrite((void *)dump, path11, dump[5]); + } + + char arm11Str[] = "Processor: ARM11 (core X)"; + if((dump[3] & 0xFFFF) == 11) arm11Str[28] = '0' + (char)(dump[3] >> 16); + initScreens(); drawString("An exception occurred", 10, 10, COLOR_RED); - int posY = drawString("Processor: ARM9", 10, 30, COLOR_WHITE) + SPACING_Y; + int posY = drawString(((dump[3] & 0xFFFF) == 11) ? arm11Str : "Processor: ARM9", 10, 30, COLOR_WHITE) + SPACING_Y; posY = drawString("Exception type: ", 10, posY, COLOR_WHITE); posY = drawString(handledExceptionNames[dump[4]], 10 + 16 * SPACING_X, posY, COLOR_WHITE); @@ -110,7 +160,7 @@ void detectAndProcessExceptionDumps(void) hexItoa(dump[10 + i], hexstring); posY = drawString(hexstring, 10 + 7 * SPACING_X, posY, COLOR_WHITE); - if(i != 16) + if(dump[3] != 9 || i != 16) { posY = drawString(registerNames[i + 1], 10 + 22 * SPACING_X, posY, COLOR_WHITE); hexItoa(dump[10 + i + 1], hexstring); @@ -122,7 +172,7 @@ void detectAndProcessExceptionDumps(void) posY += 2 * SPACING_Y; posY = drawString("You can find a dump in the following file:", 10, posY, COLOR_WHITE) + SPACING_Y; - posY = drawString(path, 10, posY, COLOR_WHITE) + 2 * SPACING_Y; + posY = drawString((dump[3] == 9) ? path9 : path11, 10, posY, COLOR_WHITE) + 2 * SPACING_Y; drawString("Press any button to shutdown", 10, posY, COLOR_WHITE); waitInput(); diff --git a/source/exceptions.h b/source/exceptions.h index c771e0d..577696c 100644 --- a/source/exceptions.h +++ b/source/exceptions.h @@ -8,4 +8,5 @@ #include "types.h" void installArm9Handlers(void); +void installArm11Handlers(u32 *exceptionsPage, u32 stackAddr); void detectAndProcessExceptionDumps(void); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 06e690c..6a7bbd6 100755 --- a/source/firm.c +++ b/source/firm.c @@ -86,7 +86,7 @@ void main(void) if(DEVMODE) { detectAndProcessExceptionDumps(); - installArm9Handlers(); + installArm9Handlers(); } bootType = 0; @@ -331,7 +331,12 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) { //Apply UNITINFO patch if(DEVMODE == 2) patchUnitInfoValueSet(arm9Section, section[2].size); - + + //Install arm11 exception handlers + u32 stackAddress; + u32 *exceptionsPage = getInfoForArm11ExceptionHandlers(arm11Section1, section[1].size, &stackAddress); + //installArm11Handlers(exceptionsPage, stackAddress); + //Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1, section[1].size); } diff --git a/source/patches.c b/source/patches.c index 1e11fb5..734a2fe 100644 --- a/source/patches.c +++ b/source/patches.c @@ -7,6 +7,8 @@ #include "config.h" #include "../build/rebootpatch.h" +static u32 *exceptionsPage = NULL; + u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { u8 *off = memsearch(pos, "ess9", size, 4); @@ -18,6 +20,20 @@ u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; } +u32* getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr) +{ + //This function has to succeed. Crash if it doesn't (we'll get an exception dump of it anyways) + + const u8 callExceptionDispatcherPattern[] = {0x0F, 0x00, 0xBD, 0xE8, 0x13, 0x00, 0x02, 0xF1}; + const u8 exceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5}; + + *stackAddr = *((u32 *)memsearch(pos, callExceptionDispatcherPattern, size, 8) + 3); + + if(exceptionsPage == NULL) exceptionsPage = (u32 *)memsearch(pos, exceptionsPagePattern, size, 4) - 0xB; + + return exceptionsPage; +} + void patchSignatureChecks(u8 *pos, u32 size) { const u16 sigPatch[2] = {0x2000, 0x4770}; @@ -152,7 +168,7 @@ void reimplementSvcBackdoor(u8 *pos, u32 size) const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; //cpsid aif - u32 *exceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; + if(exceptionsPage == NULL) exceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; u32 svcOffset = (-((exceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address diff --git a/source/patches.h b/source/patches.h index 35e4dac..b698249 100644 --- a/source/patches.h +++ b/source/patches.h @@ -16,6 +16,7 @@ typedef struct patchData { } patchData; u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); +u32* getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);