Simplified patching, yet one memsearch less, fixed override with A+L when boot options are forced
This commit is contained in:
parent
1861d556a6
commit
0f44205959
@ -45,16 +45,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
|||||||
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getMPU(void *pos, u32 size){
|
u32 *getMPU(void *pos, u32 size){
|
||||||
//Look for MPU pattern
|
//Look for MPU pattern
|
||||||
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
||||||
|
|
||||||
return memsearch(pos, pattern, size, 4);
|
return (u32 *)memsearch(pos, pattern, size, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset){
|
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset){
|
||||||
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
|
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
//Looking for the last free space before Process9
|
//Looking for the last free space before Process9
|
||||||
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - (u8 *)pos)), 4) + 0xD;
|
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - pos)), 4) + 0xD;
|
||||||
}
|
}
|
@ -13,5 +13,5 @@
|
|||||||
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
||||||
u32 getSDMMC(void *pos, u32 size);
|
u32 getSDMMC(void *pos, u32 size);
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
void *getMPU(void *pos, u32 size);
|
u32 *getMPU(void *pos, u32 size);
|
||||||
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset);
|
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset);
|
@ -92,7 +92,7 @@ void setupCFW(void){
|
|||||||
if(PDN_GPU_CNT != 0x1) loadSplash();
|
if(PDN_GPU_CNT != 0x1) loadSplash();
|
||||||
|
|
||||||
/* If L is pressed, boot 9.0 FIRM */
|
/* If L is pressed, boot 9.0 FIRM */
|
||||||
if(pressed == BUTTON_L1) mode = 0;
|
if(pressed & BUTTON_L1) mode = 0;
|
||||||
|
|
||||||
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
||||||
or R is pressed on a > 9.2 sysNAND, boot emuNAND */
|
or R is pressed on a > 9.2 sysNAND, boot emuNAND */
|
||||||
@ -191,17 +191,23 @@ static void loadEmu(u8 *proc9Offset){
|
|||||||
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
||||||
|
|
||||||
//Calculate offset for the hooks
|
//Calculate offset for the hooks
|
||||||
*(u32 *)(nandRedir + 4) = (u32)emuCodeOffset - (u32)firmLocation -
|
u32 branchOffset = (u32)emuCodeOffset - (u32)firmLocation -
|
||||||
section[2].offset + (u32)section[2].address;
|
section[2].offset + (u32)section[2].address;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
||||||
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
*(u16 *)emuRead = nandRedir[0];
|
||||||
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
|
*((u16 *)emuRead + 1) = nandRedir[1];
|
||||||
|
*((u32 *)emuRead + 1) = branchOffset;
|
||||||
|
*(u16 *)emuWrite = nandRedir[0];
|
||||||
|
*((u16 *)emuWrite + 1) = nandRedir[1];
|
||||||
|
*((u32 *)emuWrite + 1) = branchOffset;
|
||||||
|
|
||||||
//Set MPU for emu code region
|
//Set MPU for emu code region
|
||||||
void *mpuOffset = getMPU(arm9Section, section[2].size);
|
u32 *mpuOffset = getMPU(arm9Section, section[2].size);
|
||||||
memcpy(mpuOffset, mpu, sizeof(mpu));
|
*mpuOffset = mpuPatch[0];
|
||||||
|
*(mpuOffset + 6) = mpuPatch[1];
|
||||||
|
*(mpuOffset + 9) = mpuPatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
@ -221,11 +227,12 @@ void patchFirm(void){
|
|||||||
if(mode){
|
if(mode){
|
||||||
//Read reboot code from SD
|
//Read reboot code from SD
|
||||||
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
||||||
|
u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset);
|
||||||
memcpy(rebootOffset, reboot, reboot_size);
|
memcpy(rebootOffset, reboot, reboot_size);
|
||||||
|
|
||||||
//Calculate the fOpen offset and put it in the right location
|
//Put the fOpen offset in the right location
|
||||||
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
||||||
*pos_fopen = getfOpen(arm9Section, section[2].size, proc9Offset);
|
*pos_fopen = fOpenOffset;
|
||||||
|
|
||||||
//Patch path for emuNAND-patched FIRM
|
//Patch path for emuNAND-patched FIRM
|
||||||
if(emuNAND){
|
if(emuNAND){
|
||||||
@ -237,8 +244,9 @@ void patchFirm(void){
|
|||||||
|
|
||||||
if(a9lhSetup && !emuNAND){
|
if(a9lhSetup && !emuNAND){
|
||||||
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
||||||
void *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
||||||
memcpy(writeOffset, writeBlock, sizeof(writeBlock));
|
*writeOffset = writeBlock[0];
|
||||||
|
*(writeOffset + 1) = writeBlock[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disable signature checks
|
//Disable signature checks
|
||||||
@ -246,8 +254,9 @@ void patchFirm(void){
|
|||||||
sigOffset2;
|
sigOffset2;
|
||||||
|
|
||||||
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
|
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
|
||||||
memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1));
|
*(u16 *)sigOffset = sigPatch[0];
|
||||||
memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2));
|
*(u16 *)sigOffset2 = sigPatch[0];
|
||||||
|
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||||
|
|
||||||
//Patch ARM9 entrypoint on N3DS to skip arm9loader
|
//Patch ARM9 entrypoint on N3DS to skip arm9loader
|
||||||
if(console)
|
if(console)
|
||||||
|
@ -36,7 +36,7 @@ int memcmp(const void *buf1, const void *buf2, u32 size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){
|
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){
|
||||||
for(void *pos = start_pos + size - size_search; pos >= start_pos; pos--)
|
for(u8 *pos = (u8 *)start_pos + size - size_search; pos >= (u8 *)start_pos; pos--)
|
||||||
if(memcmp(pos, search, size_search) == 0) return pos;
|
if(memcmp(pos, search, size_search) == 0) return pos;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
@ -11,19 +11,13 @@
|
|||||||
* Patches
|
* Patches
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
const u8 mpu[0x2C] = {
|
const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
|
||||||
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
|
|
||||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
|
||||||
};
|
|
||||||
|
|
||||||
//Branch to emunand function. To be filled in
|
const u16 nandRedir[2] = {0x4C00, 0x47A0};
|
||||||
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
|
|
||||||
|
|
||||||
const u8 sigPat1[2] = {0x00, 0x20};
|
const u16 sigPatch[2] = {0x2000, 0x4770};
|
||||||
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
|
||||||
|
|
||||||
const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46};
|
const u16 writeBlock[2] = {0x2000, 0x46C0};
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
@ -49,22 +43,20 @@ void *getReboot(void *pos, u32 size){
|
|||||||
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
|
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset){
|
u32 getfOpen(u8 *proc9Offset, void *rebootOffset){
|
||||||
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
||||||
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
||||||
//Start of Process9 .code section (start of NCCH + ExeFS offset + ExeFS header size)
|
//Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
|
||||||
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
||||||
|
|
||||||
//Calculate fOpen
|
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||||
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
|
return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr;
|
||||||
|
|
||||||
return (u32)memsearch(pos, pattern, size, 4) - 2 - p9CodeOff + p9MemAddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getFirmWrite(void *pos, u32 size){
|
u16 *getFirmWrite(void *pos, u32 size){
|
||||||
//Look for FIRM writing code
|
//Look for FIRM writing code
|
||||||
u8 *const off = (u8 *)memsearch(pos, "exe:", size, 4);
|
u8 *const off = (u8 *)memsearch(pos, "exe:", size, 4);
|
||||||
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
||||||
|
|
||||||
return memsearch(off - 0x100, pattern, 0x100, 4);
|
return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
|
||||||
}
|
}
|
@ -11,11 +11,10 @@
|
|||||||
/**************************************************
|
/**************************************************
|
||||||
* Patches
|
* Patches
|
||||||
**************************************************/
|
**************************************************/
|
||||||
const u8 mpu[0x2C];
|
const u32 mpuPatch[3];
|
||||||
u8 nandRedir[0x08];
|
const u16 nandRedir[2];
|
||||||
const u8 sigPat1[2];
|
const u16 sigPatch[2];
|
||||||
const u8 sigPat2[4];
|
const u16 writeBlock[2];
|
||||||
const u8 writeBlock[4];
|
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
@ -23,5 +22,5 @@ const u8 writeBlock[4];
|
|||||||
u8 *getProc9(void *pos, u32 size);
|
u8 *getProc9(void *pos, u32 size);
|
||||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
||||||
void *getReboot(void *pos, u32 size);
|
void *getReboot(void *pos, u32 size);
|
||||||
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset);
|
u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
|
||||||
void *getFirmWrite(void *pos, u32 size);
|
u16 *getFirmWrite(void *pos, u32 size);
|
Reference in New Issue
Block a user