diff --git a/exceptions/arm11/source/handlers.s b/exceptions/arm11/source/handlers.s index 8dc624c..48bff21 100644 --- a/exceptions/arm11/source/handlers.s +++ b/exceptions/arm11/source/handlers.s @@ -43,33 +43,52 @@ _commonHandler: mov r6, sp mrs r3, cpsr + tst r2, #0x20 + bne noFPUInitNorSvcBreak + sub r0, lr, #4 + stmfd sp!, {lr} + bl cannotAccessVA + ldmfd sp!, {lr} + cmp r0, #0 + bne noFPUInitNorSvcBreak + ldr r4, [lr, #-4] cmp r1, #1 bne noFPUInit - tst r2, #0x20 - bne noFPUInit - ldr r4, [lr, #-4] lsl r4, #4 sub r4, #0xc0000000 cmp r4, #0x30000000 - bcs noFPUInit - fmrx r3, fpexc - tst r3, #0x40000000 - bne noFPUInit + bcs noFPUInitNorSvcBreak + fmrx r0, fpexc + tst r0, #0x40000000 + bne noFPUInitNorSvcBreak sub lr, #4 srsfd sp!, #0x13 - ldmfd sp!, {r0-r7} @ restore context - cps #0x13 @ FPU init + ldmfd sp!, {r0-r7} @ restore context + cps #0x13 @ FPU init stmfd sp, {r0-r3, r11-lr}^ sub sp, #0x20 - bl . @ will be replaced + bl . @ will be replaced ldmfd sp, {r0-r3, r11-lr}^ add sp, #0x20 rfefd sp! noFPUInit: + cmp r1, #2 + bne noFPUInitNorSvcBreak + ldr r5, =#0xe12fff7f + cmp r4, r5 + bne noFPUInitNorSvcBreak + cps #0x13 @ switch to supervisor mode + ldr r2, [sp, #0x1c] @ implementation details of the official svc handler + ldr r4, [sp, #0x18] + msr cpsr_c, r3 @ restore processor mode + tst r2, #0x20 + addne lr, r4, #2 @ adjust address for later + moveq lr, r4 + noFPUInitNorSvcBreak: ands r4, r2, #0xf @ get the mode that triggered the exception moveq r4, #0xf @ usr => sys bic r5, r3, #0xf diff --git a/exceptions/arm11/source/mainHandler.c b/exceptions/arm11/source/mainHandler.c index 5c7d286..bbeb8eb 100644 --- a/exceptions/arm11/source/mainHandler.c +++ b/exceptions/arm11/source/mainHandler.c @@ -29,20 +29,34 @@ #define CODESET_OFFSET 0xBEEFBEEF +static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment) +{ + u8 *out = (u8 *)dst; + const u8 *in = (const u8 *)src; + + if(((u32)src & (alignment - 1)) != 0 || cannotAccessVA(src) || cannotAccessVA((u8 *)src + size)) + return 0; + + for(u32 i = 0; i < size; i++) + *out++ = *in++; + + return size; +} + void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type, u32 cpuId) { ExceptionDumpHeader dumpHeader; u32 registerDump[REG_DUMP_SIZE / 4]; u8 codeDump[CODE_DUMP_SIZE]; - vu32 *final = (vu32 *)FINAL_BUFFER; + u8 *final = (u8 *)FINAL_BUFFER; - while(final[0] == 0xDEADC0DE && final[1] == 0xDEADCAFE && (final[3] == 9 || (final[3] & 0xFFFF) == 11)); + while(*(vu32 *)final == 0xDEADC0DE && *((vu32 *)final + 1) == 0xDEADCAFE); dumpHeader.magic[0] = 0xDEADC0DE; dumpHeader.magic[1] = 0xDEADCAFE; dumpHeader.versionMajor = 1; - dumpHeader.versionMinor = 1; + dumpHeader.versionMinor = 2; dumpHeader.processor = 11; dumpHeader.core = cpuId & 0xF; @@ -66,53 +80,36 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type dumpHeader.stackDumpSize = 0x1000 - (registerDump[13] & 0xFFF); //Dump code - vu8 *instr = (vu8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem - if(cannotAccessVA((u8 *)instr) || cannotAccessVA((u8 *)instr + dumpHeader.codeDumpSize)) - dumpHeader.codeDumpSize = 0; - for(u32 i = 0; i < dumpHeader.codeDumpSize; i++) - codeDump[i] = instr[i]; + u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem + dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4); //Copy register dump and code dump - final = (vu32 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader)); - - for(u32 i = 0; i < dumpHeader.registerDumpSize / 4; i++) - *final++ = registerDump[i]; - - for(u32 i = 0; i < dumpHeader.codeDumpSize / 4; i++) - *final++ = *((u32 *)codeDump + i); + final = (u8 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader)); + final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1); + final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1); //Dump stack in place - vu32 *sp = (vu32 *)registerDump[13]; - if(cannotAccessVA((u8 *)sp)) - dumpHeader.stackDumpSize = 0; - for(u32 i = 0; i < dumpHeader.stackDumpSize / 4; i++) - *final++ = sp[i]; - + dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1); vu8 *currentKProcess = (cannotAccessVA((u8 *)0xFFFF9004)) ? NULL : *(vu8 **)0xFFFF9004; - vu8 *currentKCodeSet = (currentKProcess != NULL && ((u32)currentKProcess & 3) == 0 && !cannotAccessVA((u8 *)currentKProcess + CODESET_OFFSET)) - ? *(vu8 **)(currentKProcess + CODESET_OFFSET) : NULL; + vu8 *currentKCodeSet = (currentKProcess != NULL) ? *(vu8 **)(currentKProcess + CODESET_OFFSET) : NULL; - if(currentKCodeSet != NULL && ((u32)currentKCodeSet & 3) == 0 && !cannotAccessVA((u8 *)currentKCodeSet)) + if(currentKCodeSet != NULL) { - vu32 *additionalData = final; + vu64 *additionalData = (vu64 *)final; dumpHeader.additionalDataSize = 16; - additionalData[0] = *(vu32 *)(currentKCodeSet + 0x50); //Process name - additionalData[1] = *(vu32 *)(currentKCodeSet + 0x54); - - additionalData[2] = *(vu32 *)(currentKCodeSet + 0x5C); //Title ID - additionalData[3] = *(vu32 *)(currentKCodeSet + 0x60); + additionalData[0] = *(vu64 *)(currentKCodeSet + 0x50); //Process name + additionalData[1] = *(vu64 *)(currentKCodeSet + 0x5C); //Title ID } else dumpHeader.additionalDataSize = 0; //Copy header (actually optimized by the compiler) - final = (vu32 *)FINAL_BUFFER; + final = (u8 *)FINAL_BUFFER; dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize; *(ExceptionDumpHeader *)final = dumpHeader; - cleanInvalidateDCacheAndDMB(); mcuReboot(); //Also contains DCache-cleaning code } diff --git a/exceptions/arm9/source/handlers.s b/exceptions/arm9/source/handlers.s index 97d5ef1..940a438 100644 --- a/exceptions/arm9/source/handlers.s +++ b/exceptions/arm9/source/handlers.s @@ -42,20 +42,48 @@ _commonHandler: mrs r2, spsr mov r6, sp mrs r3, cpsr - orr r3, #0x1c0 @ disable Imprecise Aborts, IRQ and FIQ (AIF) - ands r4, r2, #0xf @ get the mode that triggered the exception - moveq r4, #0xf @ usr => sys + + orr r3, #0x1c0 @ disable Imprecise Aborts, IRQ and FIQ (equivalent to "cpsid aif" on arm11) + msr cpsr_cx, r3 + + tst r2, #0x20 + bne noSvcBreak + cmp r1, #2 + bne noSvcBreak + + sub r0, lr, #4 @ calling cannotAccessAddress cause more problems that it actually solves... (I've to save a lot of regs and that's a pain tbh) + lsr r0, #20 @ we'll just do some address checks (to see if it's in ARM9 internal memory) + cmp r0, #0x80 + bne noSvcBreak + ldr r4, [lr, #-4] + ldr r5, =#0xe12fff7f + cmp r4, r5 + bne noSvcBreak + bic r5, r3, #0xf + orr r5, #0x3 + msr cpsr_c, r5 @ switch to supervisor mode + ldr r2, [sp, #0x1c] @ implementation details of the official svc handler + ldr r4, [sp, #0x18] + msr cpsr_c, r3 @ restore processor mode + tst r2, #0x20 + addne lr, r4, #2 @ adjust address for later + moveq lr, r4 + + noSvcBreak: + 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 + msr cpsr_c, r5 @ change processor mode stmfd r6!, {r8-lr} - msr cpsr_cx, r3 @ restore processor mode + msr cpsr_c, r3 @ restore processor mode mov sp, r6 - 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 + 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 mov r0, sp + b mainHandler GEN_HANDLER FIQHandler @@ -66,7 +94,7 @@ GEN_HANDLER dataAbortHandler .global readMPUConfig .type readMPUConfig, %function readMPUConfig: - stmfd sp!, {r4-r8} + stmfd sp!, {r4-r8, lr} mrc p15,0,r1,c6,c0,0 mrc p15,0,r2,c6,c1,0 mrc p15,0,r3,c6,c2,0 @@ -76,6 +104,5 @@ readMPUConfig: mrc p15,0,r7,c6,c6,0 mrc p15,0,r8,c6,c7,0 stmia r0, {r1-r8} - mrc p15,0,r0,c5,c0,2 @ read data access permission bits - ldmfd sp!, {r4-r8} - bx lr + mrc p15,0,r0,c5,c0,2 @ read data access permission bits + ldmfd sp!, {r4-r8, pc} diff --git a/exceptions/arm9/source/mainHandler.c b/exceptions/arm9/source/mainHandler.c index 25a71a8..b10e6b5 100644 --- a/exceptions/arm9/source/mainHandler.c +++ b/exceptions/arm9/source/mainHandler.c @@ -51,6 +51,20 @@ bool cannotAccessAddress(const void *address) return true; } +static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment) +{ + u8 *out = (u8 *)dst; + const u8 *in = (const u8 *)src; + + if(((u32)src & (alignment - 1)) != 0 || cannotAccessAddress(src) || cannotAccessAddress((u8 *)src + size)) + return 0; + + for(u32 i = 0; i < size; i++) + *out++ = *in++; + + return size; +} + void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type) { ExceptionDumpHeader dumpHeader; @@ -61,7 +75,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type dumpHeader.magic[0] = 0xDEADC0DE; dumpHeader.magic[1] = 0xDEADCAFE; dumpHeader.versionMajor = 1; - dumpHeader.versionMinor = 1; + dumpHeader.versionMinor = 2; dumpHeader.processor = 9; dumpHeader.core = 0; @@ -82,34 +96,25 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type for(u32 i = 0; i < 8; i++) registerDump[i] = regs[9 + i]; dumpHeader.stackDumpSize = 0x1000 - (registerDump[13] & 0xFFF); - dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize; //Dump code - vu8 *instr = (vu8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem - if(cannotAccessAddress((u8 *)instr) || cannotAccessAddress((u8 *)instr + dumpHeader.codeDumpSize)) - dumpHeader.codeDumpSize = 0; - for(u32 i = 0; i < dumpHeader.codeDumpSize; i++) - codeDump[i] = instr[i]; + u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem + dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4); - //Copy header (actually optimized by the compiler), register dump and code dump - vu32 *final = (vu32 *)FINAL_BUFFER; - *(ExceptionDumpHeader *)final = dumpHeader; - final += sizeof(ExceptionDumpHeader) / 4; - - for(u32 i = 0; i < dumpHeader.registerDumpSize / 4; i++) - *final++ = registerDump[i]; - - for(u32 i = 0; i < dumpHeader.codeDumpSize / 4; i++) - *final++ = *((u32 *)codeDump + i); + //Copy register dump and code dump + u8 *final = (u8 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader)); + final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1); + final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1); //Dump stack in place - vu32 *sp = (vu32 *)registerDump[13]; - if(cannotAccessAddress((u8 *)sp)) - dumpHeader.stackDumpSize = 0; - for(u32 i = 0; i < dumpHeader.stackDumpSize / 4; i++) - *final++ = sp[i]; + dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1); + + //Copy header (actually optimized by the compiler) + final = (u8 *)FINAL_BUFFER; + dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize; + *(ExceptionDumpHeader *)final = dumpHeader; ((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot - while(1); + while(true); } \ No newline at end of file diff --git a/exceptions/exception_dump_parser.py b/exceptions/exception_dump_parser.py index 06212f3..f704471 100644 --- a/exceptions/exception_dump_parser.py +++ b/exceptions/exception_dump_parser.py @@ -100,7 +100,7 @@ if __name__ == "__main__": version, processor, exceptionType, _, nbRegisters, codeDumpSize, stackDumpSize, additionalDataSize = unpack_from("<8I", data, 8) nbRegisters //= 4 - if version < (1 << 16) | 1: + if version < (1 << 16) | 2: raise SystemExit("Incompatible format version, please use the appropriate parser.") registers = unpack_from("<{0}I".format(nbRegisters), data, 40) @@ -114,8 +114,18 @@ if __name__ == "__main__": else: print("Processor: ARM11 (core {0})".format(processor >> 16)) typeDetailsStr = "" - if exceptionType == 2 and (registers[16] & 0x20) == 0 and codeDumpSize >= 4 and unpack_from("= 4: + instr = unpack_from("= 2: + instr = unpack_from("type], 10 + 17 * SPACING_X, posY, COLOR_WHITE); - if(dumpHeader->type == 2 && dumpHeader->registerDumpSize >= 4 && (regs[16] & 0x20) == 0 - && *(vu32 *)((vu8 *)dumpHeader + sizeof(ExceptionDumpHeader) + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize - 4) == 0xE12FFF7F) - posY = drawString("(svcBreak)", 10 + 32 * SPACING_X, posY, COLOR_WHITE); + if(dumpHeader->type == 2) + { + if((regs[16] & 0x20) == 0 && dumpHeader->codeDumpSize >= 4) + { + u32 instr = *(vu32 *)((vu8 *)dumpHeader + sizeof(ExceptionDumpHeader) + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize - 4); + if(instr == 0xE12FFF7E) + posY = drawString("(kernel panic)", 10 + 32 * SPACING_X, posY, COLOR_WHITE); + else if(instr == 0xEF00003C) + posY = drawString("(svcBreak)", 10 + 32 * SPACING_X, posY, COLOR_WHITE); + } + else if((regs[16] & 0x20) == 0 && dumpHeader->codeDumpSize >= 2) + { + u16 instr = *(vu16 *)((vu8 *)dumpHeader + sizeof(ExceptionDumpHeader) + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize - 2); + if(instr == 0xDF3C) + posY = drawString("(svcBreak)", 10 + 32 * SPACING_X, posY, COLOR_WHITE); + } + } + if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0) { posY += SPACING_Y; diff --git a/source/firm.c b/source/firm.c index 4332f17..9ab64f6 100755 --- a/source/firm.c +++ b/source/firm.c @@ -358,9 +358,12 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 //Kernel9/Process9 debugging patchExceptionHandlersInstall(arm9Section, section[2].size); patchSvcBreak9(arm9Section, section[2].size, (u32)(section[2].address)); + patchKernel9Panic(arm9Section, section[2].size); //Stub svcBreak11 with "bkpt 65535" patchSvcBreak11(arm11Section1, section[1].size); + //Stub kernel11panic with "bkpt 65534" + patchKernel11Panic(arm11Section1, section[1].size); //Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1, section[1].size); @@ -390,6 +393,7 @@ static inline void patchLegacyFirm(FirmwareType firmType) //Kernel9/Process9 debugging patchExceptionHandlersInstall(arm9Section, section[3].size); patchSvcBreak9(arm9Section, section[3].size, (u32)(section[3].address)); + patchKernel9Panic(arm9Section, section[3].size); } applyLegacyFirmPatches((u8 *)firm, firmType); @@ -414,10 +418,11 @@ static inline void patchSafeFirm(void) //Kernel9/Process9 debugging patchExceptionHandlersInstall(arm9Section, section[2].size); patchSvcBreak9(arm9Section, section[2].size, (u32)(section[2].address)); + patchKernel9Panic(arm9Section, section[2].size); } } -static inline void copySection0AndInjectSystemModules(void) +static inline void copySection0AndInjectSystemModules(FirmwareType firmType) { u8 *arm11Section0 = (u8 *)firm + section[0].offset; char fileName[] = "/luma/sysmodules/--------.cxi"; @@ -430,40 +435,45 @@ static inline void copySection0AndInjectSystemModules(void) const u8 *addr; } modules[5] = {{0}}; - u8 *pos = arm11Section0; + u8 *pos = arm11Section0, *end = pos + section[0].size; + u32 n = 0; + u32 loaderIndex = 0; - for(u32 i = 0; i < 5; i++) + + while(pos < end) { - modules[i].addr = pos; - modules[i].size = *(u32 *)(pos + 0x104) * 0x200; + modules[n].addr = pos; + modules[n].size = *(u32 *)(pos + 0x104) * 0x200; - memcpy(modules[i].name, pos + 0x200, 8); - pos += modules[i].size; + memcpy(modules[n].name, pos + 0x200, 8); + pos += modules[n].size; //Read modules from files if they exist u32 nameOff; - for(nameOff = 0; nameOff < 8 && modules[i].name[nameOff] != 0; nameOff++); - memcpy(fileName + 17, modules[i].name, nameOff); + for(nameOff = 0; nameOff < 8 && modules[n].name[nameOff] != 0; nameOff++); + memcpy(fileName + 17, modules[n].name, nameOff); memcpy(fileName + 17 + nameOff, ext, 5); u32 fileSize = getFileSize(fileName); if(fileSize != 0) { - modules[i].addr = NULL; - modules[i].size = fileSize; + modules[n].addr = NULL; + modules[n].size = fileSize; } - if(memcmp(modules[i].name, "loader", 7) == 0) loaderIndex = i; + if(firmType == NATIVE_FIRM && memcmp(modules[n].name, "loader", 7) == 0) loaderIndex = n; + + n++; } - if(modules[loaderIndex].addr != NULL) + if(firmType == NATIVE_FIRM && modules[loaderIndex].addr != NULL) { modules[loaderIndex].size = injector_size; modules[loaderIndex].addr = injector; } pos = section[0].address; - for(u32 i = 0; i < 5; i++) + for(u32 i = 0; i < n; i++) { if(modules[i].addr != NULL) memcpy(pos, modules[i].addr, modules[i].size); @@ -487,7 +497,7 @@ static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch) u32 sectionNum; if(firmType != SAFE_FIRM) { - copySection0AndInjectSystemModules(); + copySection0AndInjectSystemModules(firmType); sectionNum = 1; } else sectionNum = 0; diff --git a/source/firm.h b/source/firm.h index 8f47fe1..029929a 100644 --- a/source/firm.h +++ b/source/firm.h @@ -58,5 +58,5 @@ static inline u32 loadFirm(FirmwareType firmType); static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); -static inline void copySection0AndInjectSystemModules(void); +static inline void copySection0AndInjectSystemModules(FirmwareType firmType); static inline void launchFirm(FirmwareType firmType, bool isFirmlaunch); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 253e4d7..1ed0c7a 100644 --- a/source/patches.c +++ b/source/patches.c @@ -177,7 +177,8 @@ void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr) u32 *arm9SvcTable = (u32 *)memsearch(pos, svcHandlerPattern, size, 4); while(*arm9SvcTable) arm9SvcTable++; //Look for SVC0 (NULL) - *(u32 *)(pos + arm9SvcTable[0x3C] - k9addr) = 0xE12FFF7F; + u32 *addr = (u32 *)(pos + arm9SvcTable[0x3C] - k9addr); + *addr = 0xE12FFF7F; } void patchSvcBreak11(u8 *pos, u32 size) @@ -185,7 +186,24 @@ void patchSvcBreak11(u8 *pos, u32 size) //Same as above, for NFIRM arm11 findArm11ExceptionsPageAndSvcHandlerAndTable(pos, size); - *(u32 *)(pos + arm11SvcTable[0x3C] - 0xFFF00000) = 0xE12FFF7F; + u32 *addr = (u32 *)(pos + arm11SvcTable[0x3C] - 0xFFF00000); + *addr = 0xE12FFF7F; +} + +void patchKernel9Panic(u8 *pos, u32 size) +{ + const u8 pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x02, 0x30, 0xA0, 0xE1, 0x02, 0x10, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE3}; + + u32 *off = (u32 *)memsearch(pos, pattern, size, 16); + *off = 0xE12FFF7E; +} + +void patchKernel11Panic(u8 *pos, u32 size) +{ + const u8 pattern[] = {0x02, 0x0B, 0x44, 0xE2, 0x00, 0x10, 0x90, 0xE5}; + + u32 *off = (u32 *)memsearch(pos, pattern, size, 8); + *off = 0xE12FFF7E; } void patchArm11SvcAccessChecks(u8 *pos, u32 size) diff --git a/source/patches.h b/source/patches.h index 1e3dd6e..a4be714 100644 --- a/source/patches.h +++ b/source/patches.h @@ -45,6 +45,8 @@ void patchFirmWriteSafe(u8 *pos, u32 size); void patchExceptionHandlersInstall(u8 *pos, u32 size); void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr); void patchSvcBreak11(u8 *pos, u32 size); +void patchKernel9Panic(u8 *pos, u32 size); +void patchKernel11Panic(u8 *pos, u32 size); void patchArm11SvcAccessChecks(u8 *pos, u32 size); void patchK11ModuleChecks(u8 *pos, u32 size); void patchP9AccessChecks(u8 *pos, u32 size);