Fix derps (thanks to @Mrrraou), general cleaup, rewrite of the modules copying function
This commit is contained in:
parent
cb9576b10e
commit
e8b9e49f57
@ -24,7 +24,7 @@
|
||||
|
||||
#define FINAL_BUFFER 0xE5000000 //0x25000000
|
||||
|
||||
#define REG_DUMP_SIZE (4*23)
|
||||
#define REG_DUMP_SIZE 4 * 23
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
#define CODESET_OFFSET 0xBEEFBEEF
|
||||
@ -69,13 +69,13 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type
|
||||
//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) : 8);
|
||||
|
||||
registerDump[15] = pc;
|
||||
registerDump[16] = cpsr;
|
||||
for(u32 i = 0; i < 6; i++) registerDump[17 + i] = regs[i];
|
||||
for(u32 i = 0; i < 7; i++) registerDump[8 + i] = regs[8 + i];
|
||||
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[15 + i];
|
||||
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[15 + i];
|
||||
|
||||
//Dump code
|
||||
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
|
||||
@ -90,8 +90,8 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type
|
||||
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
|
||||
final += dumpHeader.stackDumpSize;
|
||||
|
||||
vu8 *currentKProcess = (cannotAccessVA((u8 *)0xFFFF9004)) ? NULL : *(vu8 **)0xFFFF9004;
|
||||
vu8 *currentKCodeSet = (currentKProcess != NULL) ? *(vu8 **)(currentKProcess + CODESET_OFFSET) : NULL;
|
||||
vu8 *currentKProcess = cannotAccessVA((u8 *)0xFFFF9004) ? NULL : *(vu8 **)0xFFFF9004;
|
||||
vu8 *currentKCodeSet = currentKProcess != NULL ? *(vu8 **)(currentKProcess + CODESET_OFFSET) : NULL;
|
||||
|
||||
if(currentKCodeSet != NULL)
|
||||
{
|
||||
@ -101,8 +101,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type
|
||||
additionalData[0] = *(vu64 *)(currentKCodeSet + 0x50); //Process name
|
||||
additionalData[1] = *(vu64 *)(currentKCodeSet + 0x5C); //Title ID
|
||||
}
|
||||
else
|
||||
dumpHeader.additionalDataSize = 0;
|
||||
else dumpHeader.additionalDataSize = 0;
|
||||
|
||||
//Copy header (actually optimized by the compiler)
|
||||
final = (u8 *)FINAL_BUFFER;
|
||||
@ -111,4 +110,4 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type
|
||||
|
||||
cleanInvalidateDCacheAndDMB();
|
||||
mcuReboot(); //Also contains DCache-cleaning code
|
||||
}
|
||||
}
|
@ -23,12 +23,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#define FINAL_BUFFER 0x25000000
|
||||
|
||||
#define REG_DUMP_SIZE (4*17)
|
||||
#define REG_DUMP_SIZE 4 * 17
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
bool cannotAccessAddress(const void *address)
|
||||
@ -37,7 +37,7 @@ bool cannotAccessAddress(const void *address)
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if((dataAccessPermissions & 0xF) == 0 || (regionSettings[i] & 1) == 0)
|
||||
continue; //no access / region not enabled
|
||||
continue; //No access / region not enabled
|
||||
|
||||
u32 regionAddrBase = regionSettings[i] & ~0xFFF;
|
||||
u32 regionSize = 1 << (((regionSettings[i] >> 1) & 0x1F) + 1);
|
||||
@ -88,7 +88,7 @@ void __attribute__((noreturn)) mainHandler(u32 regs[REG_DUMP_SIZE / 4], u32 type
|
||||
//Dump registers
|
||||
//Current order of saved regs: cpsr, pc, r8-r14, r0-r7
|
||||
u32 cpsr = regs[0];
|
||||
u32 pc = regs[1] - ((type < 3) ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
|
||||
u32 pc = regs[1] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
|
||||
|
||||
registerDump[15] = pc;
|
||||
registerDump[16] = cpsr;
|
||||
|
@ -23,12 +23,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
|
@ -30,27 +30,11 @@
|
||||
#include "../build/arm9_exceptions.h"
|
||||
#include "../build/arm11_exceptions.h"
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
u16 processor, core;
|
||||
u32 type;
|
||||
|
||||
u32 totalSize;
|
||||
u32 registerDumpSize;
|
||||
u32 codeDumpSize;
|
||||
u32 stackDumpSize;
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
void installArm9Handlers(void)
|
||||
{
|
||||
void *payloadAddress = (void *)0x01FF8000;
|
||||
const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
|
||||
|
||||
memcpy(payloadAddress, arm9_exceptions + 32, arm9_exceptions_size - 32);
|
||||
memcpy((void *)0x01FF8000, arm9_exceptions + 32, arm9_exceptions_size - 32);
|
||||
|
||||
//IRQHandler is at 0x08000000, but we won't handle it for some reasons
|
||||
//svcHandler is at 0x08000010, but we won't handle svc either
|
||||
@ -62,20 +46,18 @@ 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 codeSetOffset)
|
||||
{
|
||||
u32 *initFPU;
|
||||
for(initFPU = exceptionsPage; initFPU < (exceptionsPage + 0x400) && (initFPU[0] != 0xE59F0008 || initFPU[1] != 0xE5900000); initFPU += 1);
|
||||
for(initFPU = exceptionsPage; initFPU < (exceptionsPage + 0x400) && (initFPU[0] != 0xE59F0008 || initFPU[1] != 0xE5900000); initFPU++);
|
||||
|
||||
u32 *mcuReboot;
|
||||
for(mcuReboot = exceptionsPage; mcuReboot < (exceptionsPage + 0x400) && (mcuReboot[0] != 0xE59F4104 || mcuReboot[1] != 0xE3A0A0C2); mcuReboot += 1);
|
||||
for(mcuReboot = exceptionsPage; mcuReboot < (exceptionsPage + 0x400) && (mcuReboot[0] != 0xE59F4104 || mcuReboot[1] != 0xE3A0A0C2); mcuReboot++);
|
||||
mcuReboot--;
|
||||
|
||||
u32 *freeSpace;
|
||||
for(freeSpace = initFPU; freeSpace < (exceptionsPage + 0x400) && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF); freeSpace += 1);
|
||||
for(freeSpace = initFPU; freeSpace < (exceptionsPage + 0x400) && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF); freeSpace++);
|
||||
|
||||
memcpy(freeSpace, arm11_exceptions + 32, arm11_exceptions_size - 32);
|
||||
|
||||
exceptionsPage[1] = MAKE_BRANCH(exceptionsPage + 1, (u8 *)freeSpace + *(u32 *)(arm11_exceptions + 8) - 32); //Undefined Instruction
|
||||
@ -90,8 +72,8 @@ void installArm11Handlers(u32 *exceptionsPage, u32 stackAddr, u32 codeSetOffset)
|
||||
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] - 32; break; // bx r12 (mainHandler)
|
||||
case 0xBEEFBEEF: *pos = codeSetOffset;
|
||||
case 0xE12FFF1C: pos[1] = 0xFFFF0000 + 4 * (u32)(freeSpace - exceptionsPage) + pos[1] - 32; break; //bx r12 (mainHandler)
|
||||
case 0xBEEFBEEF: *pos = codeSetOffset; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -113,64 +95,61 @@ static void hexItoa(u32 n, char *out)
|
||||
|
||||
void detectAndProcessExceptionDumps(void)
|
||||
{
|
||||
const char *handledExceptionNames[] = {
|
||||
"FIQ", "undefined instruction", "prefetch abort", "data abort"
|
||||
};
|
||||
|
||||
const char *registerNames[] = {
|
||||
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
|
||||
"SP", "LR", "PC", "CPSR", "FPEXC"
|
||||
};
|
||||
|
||||
char hexstring[] = "00000000";
|
||||
|
||||
volatile ExceptionDumpHeader *dumpHeader = (volatile ExceptionDumpHeader *)0x25000000;
|
||||
vu32 *dump = (vu32 *)dumpHeader;
|
||||
vu32 *regs = (vu32 *)((vu8 *)dumpHeader + sizeof(ExceptionDumpHeader));
|
||||
vu8 *additionalData = (vu8 *)dumpHeader + dumpHeader->totalSize - dumpHeader->additionalDataSize;
|
||||
|
||||
if(dumpHeader->magic[0] == 0xDEADC0DE && dumpHeader->magic[1] == 0xDEADCAFE && (dumpHeader->processor == 9 || dumpHeader->processor == 11))
|
||||
{
|
||||
char path9[41] = "/luma/dumps/arm9";
|
||||
char path11[42] = "/luma/dumps/arm11";
|
||||
char path[42];
|
||||
char fileName[] = "crash_dump_00000000.dmp";
|
||||
u32 size = dumpHeader->totalSize;
|
||||
|
||||
char *pathFolder;
|
||||
u32 fileNameSpot;
|
||||
if(dumpHeader->processor == 9)
|
||||
{
|
||||
findDumpFile(path9, fileName);
|
||||
path9[16] = '/';
|
||||
memcpy(&path9[17], fileName, sizeof(fileName));
|
||||
if(!fileWrite((void *)dump, path9, size))
|
||||
{
|
||||
createDirectory("/luma");
|
||||
createDirectory("/luma/dumps");
|
||||
createDirectory("/luma/dumps/arm9");
|
||||
fileWrite((void *)dump, path9, size);
|
||||
}
|
||||
}
|
||||
|
||||
pathFolder = "/luma/dumps/arm9";
|
||||
fileNameSpot = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
findDumpFile(path11, fileName);
|
||||
path11[17] = '/';
|
||||
memcpy(&path11[18], fileName, sizeof(fileName));
|
||||
if(!fileWrite((void *)dump, path11, size))
|
||||
{
|
||||
createDirectory("/luma");
|
||||
createDirectory("/luma/dumps");
|
||||
createDirectory("/luma/dumps/arm11");
|
||||
fileWrite((void *)dump, path11, size);
|
||||
}
|
||||
pathFolder = "/luma/dumps/arm11";
|
||||
fileNameSpot = 17;
|
||||
}
|
||||
|
||||
findDumpFile(pathFolder, fileName);
|
||||
memcpy(path, pathFolder, 17);
|
||||
path[fileNameSpot] = '/';
|
||||
memcpy(&path[fileNameSpot + 1], fileName, sizeof(fileName));
|
||||
|
||||
if(!fileWrite((void *)dumpHeader, path, size))
|
||||
{
|
||||
createDirectory("/luma");
|
||||
createDirectory("/luma/dumps");
|
||||
createDirectory(pathFolder);
|
||||
fileWrite((void *)dumpHeader, path, size);
|
||||
}
|
||||
|
||||
vu32 *regs = (vu32 *)((vu8 *)dumpHeader + sizeof(ExceptionDumpHeader));
|
||||
vu8 *additionalData = (vu8 *)dumpHeader + dumpHeader->totalSize - dumpHeader->additionalDataSize;
|
||||
|
||||
const char *handledExceptionNames[] = {
|
||||
"FIQ", "undefined instruction", "prefetch abort", "data abort"
|
||||
};
|
||||
|
||||
const char *registerNames[] = {
|
||||
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12",
|
||||
"SP", "LR", "PC", "CPSR", "FPEXC"
|
||||
};
|
||||
|
||||
char hexstring[] = "00000000";
|
||||
|
||||
char arm11Str[] = "Processor: ARM11 (core X)";
|
||||
if(dumpHeader->processor == 11) arm11Str[29] = '0' + (char)(dumpHeader->core);
|
||||
|
||||
|
||||
initScreens();
|
||||
|
||||
drawString("An exception occurred", 10, 10, COLOR_RED);
|
||||
int posY = drawString((dumpHeader->processor == 11) ? arm11Str : "Processor: ARM9", 10, 30, COLOR_WHITE) + SPACING_Y;
|
||||
int posY = drawString(dumpHeader->processor == 11 ? arm11Str : "Processor: ARM9", 10, 30, COLOR_WHITE) + SPACING_Y;
|
||||
|
||||
posY = drawString("Exception type: ", 10, posY, COLOR_WHITE);
|
||||
posY = drawString(handledExceptionNames[dumpHeader->type], 10 + 17 * SPACING_X, posY, COLOR_WHITE);
|
||||
@ -202,6 +181,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
}
|
||||
|
||||
posY += 3 * SPACING_Y;
|
||||
|
||||
for(u32 i = 0; i < 17; i += 2)
|
||||
{
|
||||
posY = drawString(registerNames[i], 10, posY, COLOR_WHITE);
|
||||
@ -211,7 +191,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
if(dumpHeader->processor != 9 || i != 16)
|
||||
{
|
||||
posY = drawString(registerNames[i + 1], 10 + 22 * SPACING_X, posY, COLOR_WHITE);
|
||||
hexItoa((i == 16) ? regs[20] : regs[i + 1], hexstring);
|
||||
hexItoa(i == 16 ? regs[20] : regs[i + 1], hexstring);
|
||||
posY = drawString(hexstring, 10 + 29 * SPACING_X, posY, COLOR_WHITE);
|
||||
}
|
||||
|
||||
@ -223,19 +203,18 @@ void detectAndProcessExceptionDumps(void)
|
||||
u32 mode = regs[16] & 0xF;
|
||||
if(dumpHeader->type == 3 && (mode == 7 || mode == 11))
|
||||
{
|
||||
posY = drawString("Incorrect dump: failed to dump code and/or stack", 10, posY, 0x00FFFF) + 2 * SPACING_Y; //in yellow
|
||||
posY = drawString("Incorrect dump: failed to dump code and/or stack", 10, posY, 0x00FFFF) + 2 * SPACING_Y; //In yellow
|
||||
if(dumpHeader->processor != 9) posY -= SPACING_Y;
|
||||
}
|
||||
|
||||
posY = drawString("You can find a dump in the following file:", 10, posY, COLOR_WHITE) + SPACING_Y;
|
||||
posY = drawString((dumpHeader->processor == 9) ? path9 : path11, 10, posY, COLOR_WHITE) + 2 * SPACING_Y;
|
||||
posY = drawString(path, 10, posY, COLOR_WHITE) + 2 * SPACING_Y;
|
||||
drawString("Press any button to shutdown", 10, posY, COLOR_WHITE);
|
||||
|
||||
waitInput();
|
||||
|
||||
for(u32 i = 0; i < size / 4; i++) dump[i] = 0;
|
||||
|
||||
clearScreens();
|
||||
|
||||
memset32((void *)dumpHeader, 0, size);
|
||||
|
||||
mcuPowerOff();
|
||||
}
|
||||
}
|
@ -24,6 +24,24 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#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))
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic[2];
|
||||
u16 versionMinor, versionMajor;
|
||||
|
||||
u16 processor, core;
|
||||
u32 type;
|
||||
|
||||
u32 totalSize;
|
||||
u32 registerDumpSize;
|
||||
u32 codeDumpSize;
|
||||
u32 stackDumpSize;
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
void installArm9Handlers(void);
|
||||
void installArm11Handlers(u32 *exceptionsPage, u32 stackAddr, u32 codeSetOffset);
|
||||
void detectAndProcessExceptionDumps(void);
|
109
source/firm.c
109
source/firm.c
@ -43,7 +43,9 @@ static const firmSectionHeader *section;
|
||||
|
||||
u32 emuOffset;
|
||||
|
||||
bool isN3DS, isDevUnit, isFirmlaunch;
|
||||
bool isN3DS,
|
||||
isDevUnit,
|
||||
isFirmlaunch;
|
||||
|
||||
cfgData configData;
|
||||
FirmwareSource firmSource;
|
||||
@ -239,6 +241,7 @@ void main(void)
|
||||
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
{
|
||||
section = firm->section;
|
||||
|
||||
const char *firmwareFiles[4] = {
|
||||
"/luma/firmware.bin",
|
||||
"/luma/firmware_twl.bin",
|
||||
@ -248,13 +251,10 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
|
||||
u32 firmVersion;
|
||||
|
||||
if(fileRead(firm, firmwareFiles[(u32)firmType]))
|
||||
{
|
||||
firmVersion = 0xFFFFFFFF;
|
||||
}
|
||||
if(fileRead(firm, firmwareFiles[(u32)*firmType])) firmVersion = 0xFFFFFFFF;
|
||||
else
|
||||
{
|
||||
firmVersion = firmRead(firm, (u32)firmType);
|
||||
firmVersion = firmRead(firm, (u32)*firmType);
|
||||
|
||||
if(!isN3DS && *firmType == NATIVE_FIRM)
|
||||
{
|
||||
@ -279,9 +279,9 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource)
|
||||
firmVersion = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(firmVersion != 0xFFFFFFFF) decryptExeFs((u8 *)firm);
|
||||
decryptExeFs((u8 *)firm);
|
||||
}
|
||||
|
||||
return firmVersion;
|
||||
}
|
||||
@ -340,22 +340,23 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
||||
}
|
||||
|
||||
implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, &freeK11Space);
|
||||
|
||||
|
||||
//Apply UNITINFO patch
|
||||
if(DEV_OPTIONS == 1) patchUnitInfoValueSet(arm9Section, section[2].size);
|
||||
|
||||
if(DEV_OPTIONS != 2)
|
||||
{
|
||||
//Install arm11 exception handlers
|
||||
u32 stackAddress, codeSetOffset;
|
||||
u32 stackAddress,
|
||||
codeSetOffset;
|
||||
getInfoForArm11ExceptionHandlers(arm11Section1, section[1].size, &stackAddress, &codeSetOffset);
|
||||
installArm11Handlers(arm11ExceptionsPage, stackAddress, codeSetOffset);
|
||||
|
||||
|
||||
//Kernel9/Process9 debugging
|
||||
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)(section[2].address));
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address);
|
||||
patchKernel9Panic(arm9Section, section[2].size, NATIVE_FIRM);
|
||||
|
||||
|
||||
//Stub svcBreak11 with "bkpt 65535"
|
||||
patchSvcBreak11(arm11Section1, arm11SvcTable);
|
||||
|
||||
@ -389,7 +390,7 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
{
|
||||
//Kernel9/Process9 debugging
|
||||
patchArm9ExceptionHandlersInstall(arm9Section, section[3].size);
|
||||
patchSvcBreak9(arm9Section, section[3].size, (u32)(section[3].address));
|
||||
patchSvcBreak9(arm9Section, section[3].size, (u32)section[3].address);
|
||||
patchKernel9Panic(arm9Section, section[3].size, firmType);
|
||||
}
|
||||
|
||||
@ -416,71 +417,49 @@ static inline void patch2xNativeAndSafeFirm(void)
|
||||
{
|
||||
//Kernel9/Process9 debugging
|
||||
patchArm9ExceptionHandlersInstall(arm9Section, section[2].size);
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)(section[2].address));
|
||||
patchSvcBreak9(arm9Section, section[2].size, (u32)section[2].address);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void copySection0AndInjectSystemModules(FirmwareType firmType)
|
||||
{
|
||||
u8 *arm11Section0 = (u8 *)firm + section[0].offset;
|
||||
char fileName[] = "/luma/sysmodules/--------.cxi";
|
||||
const char *ext = ".cxi";
|
||||
u32 srcModuleSize,
|
||||
dstModuleSize;
|
||||
|
||||
struct
|
||||
for(u8 *src = (u8 *)firm + section[0].offset, *srcEnd = src + section[0].size, *dst = section[0].address;
|
||||
src < srcEnd; src += srcModuleSize, dst += dstModuleSize)
|
||||
{
|
||||
u32 size;
|
||||
char name[8];
|
||||
const u8 *addr;
|
||||
} modules[5];
|
||||
srcModuleSize = *(u32 *)(src + 0x104) * 0x200;
|
||||
char *moduleName = (char *)(src + 0x200);
|
||||
|
||||
u8 *pos = arm11Section0;
|
||||
u32 n = 0;
|
||||
char fileName[30] = "/luma/sysmodules/";
|
||||
const char *ext = ".cxi";
|
||||
|
||||
u32 loaderIndex = 0;
|
||||
|
||||
for(u8 *end = pos + section[0].size; pos < end; pos += modules[n++].size)
|
||||
{
|
||||
modules[n].addr = pos;
|
||||
modules[n].size = *(u32 *)(pos + 0x104) * 0x200;
|
||||
|
||||
memcpy(modules[n].name, pos + 0x200, 8);
|
||||
|
||||
//Read modules from files if they exist
|
||||
u32 nameOff;
|
||||
for(nameOff = 0; nameOff < 8 && modules[n].name[nameOff] != 0; nameOff++);
|
||||
memcpy(fileName + 17, modules[n].name, nameOff);
|
||||
for(nameOff = 0; nameOff < 8 && moduleName[nameOff] != 0; nameOff++);
|
||||
memcpy(fileName + 17, moduleName, nameOff);
|
||||
memcpy(fileName + 17 + nameOff, ext, 5);
|
||||
|
||||
u32 fileSize = getFileSize(fileName);
|
||||
if(fileSize != 0)
|
||||
{
|
||||
modules[n].addr = NULL;
|
||||
modules[n].size = fileSize;
|
||||
}
|
||||
|
||||
if(firmType == NATIVE_FIRM && memcmp(modules[n].name, "loader", 7) == 0) loaderIndex = n;
|
||||
}
|
||||
|
||||
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 < n; pos += modules[i++].size)
|
||||
{
|
||||
if(modules[i].addr != NULL)
|
||||
memcpy(pos, modules[i].addr, modules[i].size);
|
||||
u32 fileSize = fileRead(dst, fileName);
|
||||
if(fileSize) dstModuleSize = fileSize;
|
||||
else
|
||||
{
|
||||
//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);
|
||||
memcpy(fileName + 17 + nameOff, ext, 5);
|
||||
fileRead(pos, fileName);
|
||||
}
|
||||
void *module;
|
||||
|
||||
if(firmType == NATIVE_FIRM && memcmp(moduleName, "loader", 6) == 0)
|
||||
{
|
||||
module = (void *)injector;
|
||||
dstModuleSize = injector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
module = src;
|
||||
dstModuleSize = srcModuleSize;
|
||||
}
|
||||
|
||||
memcpy(dst, module, dstModuleSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,4 +495,4 @@ static inline void launchFirm(FirmwareType firmType)
|
||||
|
||||
//Final jump to ARM9 kernel
|
||||
((void (*)())firm->arm9Entry)();
|
||||
}
|
||||
}
|
@ -260,14 +260,12 @@ void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size)
|
||||
0x20, 0x10, 0x80, 0xE5,
|
||||
0x28, 0x10, 0x80, 0xE5,
|
||||
}; //i.e when it stores ldr pc, [pc, #-4]
|
||||
|
||||
|
||||
u32* off = (u32 *)(memsearch(pos, pattern, size, sizeof(pattern)));
|
||||
if(off == NULL) return;
|
||||
off += sizeof(pattern)/4;
|
||||
|
||||
u32 r0 = 0x08000000;
|
||||
|
||||
for(; *off != 0xE3A01040; off++) //Until mov r1, #0x40
|
||||
for(u32 r0 = 0x08000000; *off != 0xE3A01040; off++) //Until mov r1, #0x40
|
||||
{
|
||||
if((*off >> 26) != 0x39 || ((*off >> 16) & 0xF) != 0 || ((*off >> 25) & 1) != 0 || ((*off >> 20) & 5) != 0)
|
||||
continue; //Discard everything that's not str rX, [r0, #imm](!)
|
||||
@ -288,7 +286,7 @@ void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr)
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9Address)
|
||||
{
|
||||
//Stub svcBreak with "bkpt 65535" so we can debug the panic.
|
||||
//Thanks @yellows8 and others for mentioning this idea on #3dsdev.
|
||||
@ -296,14 +294,14 @@ void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr)
|
||||
|
||||
u32 *arm9SvcTable = (u32 *)memsearch(pos, svcHandlerPattern, size, 4);
|
||||
while(*arm9SvcTable) arm9SvcTable++; //Look for SVC0 (NULL)
|
||||
u32 *addr = (u32 *)(pos + arm9SvcTable[0x3C] - k9addr);
|
||||
|
||||
u32 *addr = (u32 *)(pos + arm9SvcTable[0x3C] - k9Address);
|
||||
*addr = 0xE12FFF7F;
|
||||
}
|
||||
|
||||
void patchSvcBreak11(u8 *pos, u32 *arm11SvcTable)
|
||||
{
|
||||
//Same as above, for NFIRM arm11
|
||||
|
||||
u32 *addr = (u32 *)(pos + arm11SvcTable[0x3C] - 0xFFF00000);
|
||||
*addr = 0xE12FFF7F;
|
||||
}
|
||||
@ -312,12 +310,11 @@ void patchKernel9Panic(u8 *pos, u32 size, FirmwareType firmType)
|
||||
{
|
||||
if(firmType == TWL_FIRM || firmType == AGB_FIRM)
|
||||
{
|
||||
u8 *off = pos + ((isN3DS) ? 0x723C : 0x69A8);
|
||||
u8 *off = pos + (isN3DS ? 0x723C : 0x69A8);
|
||||
*(u16 *)off = 0x4778; //bx pc
|
||||
*(u16 *)(off + 2) = 0x46C0; //nop
|
||||
*(u32 *)(off + 4) = 0xE12FFF7E; //bkpt 65534
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
const u8 pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x02, 0x30, 0xA0, 0xE1, 0x02, 0x10, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE3};
|
||||
@ -337,41 +334,34 @@ void patchKernel11Panic(u8 *pos, u32 size)
|
||||
|
||||
void patchArm11SvcAccessChecks(u32 *arm11SvcHandler)
|
||||
{
|
||||
u32 *off = arm11SvcHandler;
|
||||
while(*off != 0xE11A0E1B) off++; //TST R10, R11,LSL LR
|
||||
|
||||
*off = 0xE3B0A001; //MOVS R10, #1
|
||||
while(*arm11SvcHandler != 0xE11A0E1B) arm11SvcHandler++; //TST R10, R11,LSL LR
|
||||
*arm11SvcHandler = 0xE3B0A001; //MOVS R10, #1
|
||||
}
|
||||
|
||||
//It's mainly Subv's code here:
|
||||
void patchK11ModuleChecks(u8 *pos, u32 size, u8 **freeK11Space)
|
||||
{
|
||||
// We have to detour a function in the ARM11 kernel because builtin modules
|
||||
// are compressed in memory and are only decompressed at runtime.
|
||||
|
||||
u8 *freeSpace = *freeK11Space;
|
||||
*freeK11Space += k11modules_size;
|
||||
//We have to detour a function in the ARM11 kernel because builtin modules
|
||||
//are compressed in memory and are only decompressed at runtime.
|
||||
|
||||
// Inject our code into the free space
|
||||
memcpy(freeSpace, k11modules, k11modules_size);
|
||||
//Inject our code into the free space
|
||||
memcpy(*freeK11Space, k11modules, k11modules_size);
|
||||
(*freeK11Space) += k11modules_size;
|
||||
|
||||
// Find the code that decompresses the .code section of the builtin modules and detour it with a jump to our code
|
||||
//Find the code that decompresses the .code section of the builtin modules and detour it with a jump to our code
|
||||
const u8 pattern[] = { 0x00, 0x00, 0x94, 0xE5, 0x18, 0x10, 0x90, 0xE5, 0x28, 0x20,
|
||||
0x90, 0xE5, 0x48, 0x00, 0x9D, 0xE5 };
|
||||
|
||||
u8 *off = memsearch(pos, pattern, size, 16);
|
||||
u32 *off = (u32 *)memsearch(pos, pattern, size, 16);
|
||||
|
||||
// We couldn't find the code that decompresses the module
|
||||
if (off == NULL)
|
||||
return;
|
||||
//We couldn't find the code that decompresses the module
|
||||
if(off == NULL) return;
|
||||
|
||||
// Inject a jump instruction to our code at the offset we found
|
||||
// Construct a jump (BL) instruction to our code
|
||||
u32 offset = ((((u32)freeSpace) - ((u32)off + 8)) >> 2) & 0xFFFFFF;
|
||||
u32 instruction = offset | (1 << 24) | (0x5 << 25) | (0xE << 28);
|
||||
//Inject a jump instruction to our code at the offset we found
|
||||
//Construct a jump (BL) instruction to our code
|
||||
u32 offset = ((((u32)*freeK11Space) - ((u32)off + 8)) >> 2) & 0xFFFFFF;
|
||||
|
||||
// Write our jump
|
||||
memcpy(off, &instruction, 4);
|
||||
*off = offset | (1 << 24) | (0x5 << 25) | (0xE << 28);
|
||||
}
|
||||
|
||||
void patchP9AccessChecks(u8 *pos, u32 size)
|
||||
@ -384,7 +374,6 @@ void patchP9AccessChecks(u8 *pos, u32 size)
|
||||
off[1] = 0x4770; //bx lr
|
||||
}
|
||||
|
||||
|
||||
void patchUnitInfoValueSet(u8 *pos, u32 size)
|
||||
{
|
||||
//Look for UNITINFO value being set during kernel sync
|
||||
@ -392,6 +381,6 @@ void patchUnitInfoValueSet(u8 *pos, u32 size)
|
||||
|
||||
u8 *off = memsearch(pos, pattern, size, 4);
|
||||
|
||||
off[0] = (isDevUnit) ? 0 : 1;
|
||||
off[0] = isDevUnit ? 0 : 1;
|
||||
off[3] = 0xE3;
|
||||
}
|
@ -63,7 +63,7 @@ void patchTwlBg(u8 *pos);
|
||||
|
||||
void getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr, u32 *codeSetOffset);
|
||||
void patchArm9ExceptionHandlersInstall(u8 *pos, u32 size);
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr);
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9Address);
|
||||
void patchSvcBreak11(u8 *pos, u32 *arm11SvcTable);
|
||||
void patchKernel9Panic(u8 *pos, u32 size, FirmwareType firmType);
|
||||
void patchKernel11Panic(u8 *pos, u32 size);
|
||||
|
Reference in New Issue
Block a user