Fix ldrt/sdrt handling.

This commit is contained in:
TuxSH 2016-12-22 23:11:15 +01:00
parent f89845257e
commit 0ba7630354
6 changed files with 45 additions and 20 deletions

View File

@ -67,7 +67,7 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
//Dump registers //Dump registers
//Current order of saved regs: dfsr, ifsr, far, fpexc, fpinst, fpinst2, cpsr, pc, r8-r12, sp, lr, r0-r7 //Current order of saved regs: dfsr, ifsr, far, fpexc, fpinst, fpinst2, cpsr, pc, r8-r12, sp, lr, r0-r7
u32 cpsr = regs[6]; 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[15] = pc;
registerDump[16] = cpsr; registerDump[16] = cpsr;
@ -106,4 +106,4 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
cleanInvalidateDCacheAndDMB(); cleanInvalidateDCacheAndDMB();
mcuReboot(); //Also contains DCache-cleaning code mcuReboot(); //Also contains DCache-cleaning code
} }

View File

@ -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; 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[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[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 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++) for(u32 *pos = freeSpace; pos < (u32 *)((u8 *)freeSpace + arm11_exceptions_bin_size - 32); pos++)
{ {
switch(*pos) //Perform relocations 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 0xEBFFFFFE: *pos = MAKE_BRANCH_LINK(pos, initFPU); break;
case 0xEAFFFFFE: *pos = MAKE_BRANCH(pos, mcuReboot); 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) 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 *stackDump = (vu8 *)regs + dumpHeader->registerDumpSize + dumpHeader->codeDumpSize;
const vu8 *additionalData = stackDump + dumpHeader->stackDumpSize; const vu8 *additionalData = stackDump + dumpHeader->stackDumpSize;
const char *handledExceptionNames[] = { const char *handledExceptionNames[] = {
"FIQ", "undefined instruction", "prefetch abort", "data abort" "FIQ", "undefined instruction", "prefetch abort", "data abort"
}; };
@ -200,4 +221,4 @@ void detectAndProcessExceptionDumps(void)
waitInput(false); waitInput(false);
mcuPowerOff(); mcuPowerOff();
} }

View File

@ -28,5 +28,5 @@
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF)) #define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
void installArm9Handlers(void); void installArm9Handlers(void);
u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset); u32 installArm11Handlers(u32 *exceptionsPage, u32 stackAddress, u32 codeSetOffset, u32 *dAbtHandler, u32 dAbtHandlerMemAddress);
void detectAndProcessExceptionDumps(void); void detectAndProcessExceptionDumps(void);

View File

@ -89,7 +89,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora
if(firmVersion < 0x18) if(firmVersion < 0x18)
{ {
//We can't boot < 3.x EmuNANDs //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."); 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."); 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; u32 baseK11VA;
u8 *freeK11Space; u8 *freeK11Space;
u32 *arm11SvcHandler, u32 *arm11SvcHandler,
*arm11DAbtHandler,
*arm11ExceptionsPage, *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, u32 kernel9Size = (u32)(process9Offset - arm9Section) - sizeof(Cxi) - 0x200,
ret = 0; ret = 0;
@ -185,7 +186,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, boo
//ARM11 exception handlers //ARM11 exception handlers
u32 codeSetOffset, u32 codeSetOffset,
stackAddress = getInfoForArm11ExceptionHandlers(arm11Section1, firm->section[1].size, &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); patchSvcBreak11(arm11Section1, arm11SvcTable);
ret += patchKernel11Panic(arm11Section1, firm->section[1].size); 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) u32 patchTwlFirm(u32 firmVersion, u32 devMode)
{ {
u8 *arm9Section = (u8 *)firm + firm->section[3].offset; u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
if(ISN3DS) if(ISN3DS)
{ {
@ -248,7 +249,7 @@ u32 patchTwlFirm(u32 firmVersion, u32 devMode)
u32 patchAgbFirm(u32 devMode) u32 patchAgbFirm(u32 devMode)
{ {
u8 *arm9Section = (u8 *)firm + firm->section[3].offset; u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
if(ISN3DS) if(ISN3DS)
{ {
@ -393,4 +394,4 @@ void launchFirm(FirmwareType firmType, bool loadFromStorage)
//Final jump to ARM9 kernel //Final jump to ARM9 kernel
((void (*)())firm->arm9Entry)(); ((void (*)())firm->arm9Entry)();
} }

View File

@ -73,7 +73,7 @@ u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
return (u8 *)off + (off->ncch.exeFsOffset + 1) * 0x200; 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}, const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5},
pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
@ -87,14 +87,17 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
*arm11ExceptionsPage -= 0xB; *arm11ExceptionsPage -= 0xB;
u32 svcOffset = (-(((*arm11ExceptionsPage)[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch 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; u32 pointedInstructionVA = 0xFFFF0008 - svcOffset;
*baseK11VA = pointedInstructionVA & 0xFFFF0000; //This assumes that the pointed instruction has an offset < 0x10000, iirc that's always the case *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 arm11SvcTable = *arm11SvcHandler = (u32 *)(pos + *(u32 *)(pos + pointedInstructionVA - *baseK11VA + 8) - *baseK11VA); //SVC handler address
while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL)
pointedInstructionVA = 0xFFFF0010 - dabtOffset;
*arm11DAbtHandler = (u32 *)(pos + *(u32 *)(pos + pointedInstructionVA - *baseK11VA + 8) - *baseK11VA);
(*freeK11Space)++; (*freeK11Space)++;
return arm11SvcTable; return arm11SvcTable;
} }
u32 patchSignatureChecks(u8 *pos, u32 size) u32 patchSignatureChecks(u8 *pos, u32 size)
@ -590,4 +593,4 @@ u32 patchAgbBootSplash(u8 *pos, u32 size)
off[2] = 0x26; off[2] = 0x26;
return 0; return 0;
} }

View File

@ -35,7 +35,7 @@
extern CfgData configData; extern CfgData configData;
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); 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 patchSignatureChecks(u8 *pos, u32 size);
u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
u32 patchFirmWrites(u8 *pos, u32 size); 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 patchTwlFlashcartChecks(u8 *pos, u32 size, u32 firmVersion);
u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size); u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size);
u32 patchTwlShaHashChecks(u8 *pos, u32 size); u32 patchTwlShaHashChecks(u8 *pos, u32 size);
u32 patchAgbBootSplash(u8 *pos, u32 size); u32 patchAgbBootSplash(u8 *pos, u32 size);