Fix ldrt/sdrt handling.
This commit is contained in:
parent
f89845257e
commit
0ba7630354
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,11 +87,14 @@ 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;
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user