diff --git a/exceptions/arm11/source/mainHandler.c b/exceptions/arm11/source/mainHandler.c index 3e231b8..22e53d8 100644 --- a/exceptions/arm11/source/mainHandler.c +++ b/exceptions/arm11/source/mainHandler.c @@ -67,7 +67,7 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId) //Dump registers //Current order of saved regs: dfsr, ifsr, far, fpexc, fpinst, fpinst2, cpsr, pc, r8-r12, sp, lr, r0-r7 u32 cpsr = regs[6]; - u32 pc = regs[7] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8); + u32 pc = regs[7] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 0); registerDump[15] = pc; registerDump[16] = cpsr; @@ -106,4 +106,4 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId) cleanInvalidateDCacheAndDMB(); mcuReboot(); //Also contains DCache-cleaning code -} \ No newline at end of file +} diff --git a/source/exceptions.c b/source/exceptions.c index d738e0d..bb595db 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -45,7 +45,7 @@ void installArm9Handlers(void) } } -u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset) +u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset, u32 *dAbtHandler, u32 dAbtHandlerMemAddress) { u32 *endPos = exceptionsPage + 0x400; @@ -67,14 +67,35 @@ u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffse exceptionsPage[1] = MAKE_BRANCH(exceptionsPage + 1, (u8 *)freeSpace + *(u32 *)(arm11_exceptions_bin + 8) - 32); //Undefined Instruction exceptionsPage[3] = MAKE_BRANCH(exceptionsPage + 3, (u8 *)freeSpace + *(u32 *)(arm11_exceptions_bin + 12) - 32); //Prefetch Abort - exceptionsPage[4] = MAKE_BRANCH(exceptionsPage + 4, (u8 *)freeSpace + *(u32 *)(arm11_exceptions_bin + 16) - 32); //Data Abort exceptionsPage[7] = MAKE_BRANCH(exceptionsPage + 7, (u8 *)freeSpace + *(u32 *)(arm11_exceptions_bin + 4) - 32); //FIQ + for(u32 *pos = dAbtHandler; *pos != stackAddress; pos++) + { + u32 va_dst = 0xFFFF0000 + (((u8 *)freeSpace + *(u32 *)(arm11_exceptions_bin + 4)) - (u8 *)exceptionsPage); + u32 va_src; + switch(*pos) + { + case 0xF96D0513: //srsdb sp!, 0x13 + va_src = dAbtHandlerMemAddress + ((u8 *)pos - (u8 *)dAbtHandler); + *pos = MAKE_BRANCH((u8 *)va_src, (u8 *)va_dst); + break; + case 0xE29EF004: //subs pc, lr, 4 + pos++; + *pos++ = 0xE8BD000F;// pop {r0-r3} + va_src = dAbtHandlerMemAddress + ((u8 *)pos - (u8 *)dAbtHandler); + *pos = MAKE_BRANCH((u8 *)va_src, (u8 *)va_dst); + break; + default: + break; + } + } + + for(u32 *pos = freeSpace; pos < (u32 *)((u8 *)freeSpace + arm11_exceptions_bin_size - 32); pos++) { switch(*pos) //Perform relocations { - case 0xFFFF3000: *pos = stackAddress; break; + case 0xFFFF3000: *pos = stackAddress - 0x10; 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] - 32; break; //bx r12 (mainHandler) @@ -95,7 +116,7 @@ void detectAndProcessExceptionDumps(void) const vu8 *stackDump = (vu8 *)regs + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize; const vu8 *additionalData = stackDump + dumpHeader->stackDumpSize; - const char *handledExceptionNames[] = { + const char *handledExceptionNames[] = { "FIQ", "undefined instruction", "prefetch abort", "data abort" }; @@ -200,4 +221,4 @@ void detectAndProcessExceptionDumps(void) waitInput(false); mcuPowerOff(); -} \ No newline at end of file +} diff --git a/source/exceptions.h b/source/exceptions.h index ed0b584..a9aa5b1 100644 --- a/source/exceptions.h +++ b/source/exceptions.h @@ -28,5 +28,5 @@ #define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) void installArm9Handlers(void); -u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset); -void detectAndProcessExceptionDumps(void); \ No newline at end of file +u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset, u32 *dAbtHandler, u32 dAbtHandlerMemAddress); +void detectAndProcessExceptionDumps(void); diff --git a/source/firm.c b/source/firm.c index 4b38eda..14e0870 100755 --- a/source/firm.c +++ b/source/firm.c @@ -89,7 +89,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora if(firmVersion < 0x18) { //We can't boot < 3.x EmuNANDs - if(nandType != FIRMWARE_SYSNAND) + if(nandType != FIRMWARE_SYSNAND) error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it."); if(isSafeMode) error("SAFE_MODE is not supported on 1.x/2.x FIRM."); @@ -136,8 +136,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo u32 baseK11VA; u8 *freeK11Space; u32 *arm11SvcHandler, + *arm11DAbtHandler, *arm11ExceptionsPage, - *arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage); + *arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11DAbtHandler, &arm11ExceptionsPage); u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200, ret = 0; @@ -185,7 +186,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo //ARM11 exception handlers u32 codeSetOffset, stackAddress = getInfoForArm11ExceptionHandlers(arm11Section1, firm->section[1].size, &codeSetOffset); - ret += installArm11Handlers(arm11ExceptionsPage, stackAddress, codeSetOffset); + ret += installArm11Handlers(arm11ExceptionsPage, stackAddress, codeSetOffset, arm11DAbtHandler, baseK11VA + ((u8 *)arm11DAbtHandler - arm11Section1)); patchSvcBreak11(arm11Section1, arm11SvcTable); ret += patchKernel11Panic(arm11Section1, firm->section[1].size); @@ -215,7 +216,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo u32 patchTwlFirm(u32 firmVersion, u32 devMode) { u8 *arm9Section = (u8 *)firm + firm->section[3].offset; - + //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader if(ISN3DS) { @@ -248,7 +249,7 @@ u32 patchTwlFirm(u32 firmVersion, u32 devMode) u32 patchAgbFirm(u32 devMode) { u8 *arm9Section = (u8 *)firm + firm->section[3].offset; - + //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader if(ISN3DS) { @@ -393,4 +394,4 @@ void launchFirm(FirmwareType firmType, bool loadFromStorage) //Final jump to ARM9 kernel ((void (*)())firm->arm9Entry)(); -} \ No newline at end of file +} diff --git a/source/patches.c b/source/patches.c index 91f2542..aa382ac 100644 --- a/source/patches.c +++ b/source/patches.c @@ -73,7 +73,7 @@ u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200; } -u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage) +u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11DAbtHandler, u32 **arm11ExceptionsPage) { const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}, pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -87,14 +87,17 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 * *arm11ExceptionsPage -= 0xB; u32 svcOffset = (-(((*arm11ExceptionsPage)[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch + u32 dabtOffset = (-(((*arm11ExceptionsPage)[4] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch u32 pointedInstructionVA = 0xFFFF0008 - svcOffset; *baseK11VA = pointedInstructionVA & 0xFFFF0000; //This assumes that the pointed instruction has an offset < 0x10000, iirc that's always the case arm11SvcTable = *arm11SvcHandler = (u32 *)(pos + *(u32 *)(pos + pointedInstructionVA - *baseK11VA + 8) - *baseK11VA); //SVC handler address while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) + pointedInstructionVA = 0xFFFF0010 - dabtOffset; + *arm11DAbtHandler = (u32 *)(pos + *(u32 *)(pos + pointedInstructionVA - *baseK11VA + 8) - *baseK11VA); (*freeK11Space)++; - return arm11SvcTable; + return arm11SvcTable; } u32 patchSignatureChecks(u8 *pos, u32 size) @@ -590,4 +593,4 @@ u32 patchAgbBootSplash(u8 *pos, u32 size) off[2] = 0x26; return 0; -} \ No newline at end of file +} diff --git a/source/patches.h b/source/patches.h index 34f92aa..4f20015 100644 --- a/source/patches.h +++ b/source/patches.h @@ -35,7 +35,7 @@ extern CfgData configData; u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); -u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); +u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11DAbtHandler, u32 **arm11ExceptionsPage); u32 patchSignatureChecks(u8 *pos, u32 size); u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); u32 patchFirmWrites(u8 *pos, u32 size); @@ -63,4 +63,4 @@ u32 patchTwlWhitelistChecks(u8 *pos, u32 size); u32 patchTwlFlashcartChecks(u8 *pos, u32 size, u32 firmVersion); u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size); u32 patchTwlShaHashChecks(u8 *pos, u32 size); -u32 patchAgbBootSplash(u8 *pos, u32 size); \ No newline at end of file +u32 patchAgbBootSplash(u8 *pos, u32 size);