diff --git a/source/emunand.c b/source/emunand.c index 2b6f02c..0115a1c 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -25,12 +25,12 @@ #include "fatfs/sdmmc/sdmmc.h" #include "../build/emunandpatch.h" -void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND) +void locateEmuNand(u32 *off, u32 *head, FirmwareSource *emuNand) { static u8 temp[0x200]; const u32 nandSize = getMMCDevice(0)->total_size; - u32 nandOffset = *emuNAND == FIRMWARE_EMUNAND ? 0 : + u32 nandOffset = *emuNand == FIRMWARE_EMUNAND ? 0 : (nandSize > 0x200000 ? 0x400000 : 0x200000); //Check for RedNAND @@ -53,12 +53,12 @@ void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND) or to SysNAND if there isn't any */ else { - *emuNAND = (*emuNAND == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; - if(*emuNAND) locateEmuNAND(off, head, emuNAND); + *emuNand = (*emuNand == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; + if(*emuNand) locateEmuNand(off, head, emuNand); } } -static inline void *getEmuCode(u8 *pos, u32 size) +static inline void *getFreeK9Space(u8 *pos, u32 size) { const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; @@ -66,7 +66,7 @@ static inline void *getEmuCode(u8 *pos, u32 size) return memsearch(pos + 0x13500, pattern, size - 0x13500, 6) + 0x455; } -static inline u32 getSDMMC(u8 *pos, u32 size) +static inline u32 getSdmmc(u8 *pos, u32 size) { //Look for struct code const u8 pattern[] = {0x21, 0x20, 0x18, 0x20}; @@ -75,7 +75,7 @@ static inline u32 getSDMMC(u8 *pos, u32 size) return *(u32 *)(off + 9) + *(u32 *)(off + 0xD); } -static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset) +static inline void patchNandRw(u8 *pos, u32 size, u32 branchOffset) { const u16 nandRedir[2] = {0x4C00, 0x47A0}; @@ -93,7 +93,7 @@ static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset) ((u32 *)writeOffset)[1] = branchOffset; } -static inline void patchMPU(u8 *pos, u32 size) +static inline void patchMpu(u8 *pos, u32 size) { const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603}; @@ -107,26 +107,26 @@ static inline void patchMPU(u8 *pos, u32 size) off[9] = mpuPatch[2]; } -void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuOffset, u32 emuHeader, u32 branchAdditive) +void patchEmuNand(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuHeader, u32 branchAdditive) { //Copy emuNAND code - void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize); - memcpy(emuCodeOffset, emunand, emunand_size); + void *freeK9Space = getFreeK9Space(arm9Section, arm9SectionSize); + memcpy(freeK9Space, emunand, emunand_size); //Add the data of the found emuNAND - u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4), - *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4); - *pos_offset = emuOffset; - *pos_header = emuHeader; + u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_size, 4), + *posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_size, 4); + *posOffset = emuOffset; + *posHeader = emuHeader; //Find and add the SDMMC struct - u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4); - *pos_sdmmc = getSDMMC(process9Offset, process9Size); + u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_size, 4); + *posSdmmc = getSdmmc(process9Offset, process9Size); //Add emuNAND hooks - u32 branchOffset = (u32)emuCodeOffset - branchAdditive; - patchNANDRW(process9Offset, process9Size, branchOffset); + u32 branchOffset = (u32)freeK9Space - branchAdditive; + patchNandRw(process9Offset, process9Size, branchOffset); //Set MPU for emu code region - patchMPU(arm9Section, arm9SectionSize); + patchMpu(arm9Section, arm9SectionSize); } \ No newline at end of file diff --git a/source/emunand.h b/source/emunand.h index 1930c34..543fbe0 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -26,5 +26,7 @@ #define NCSD_MAGIC 0x4453434E -void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND); -void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuOffset, u32 emuHeader, u32 branchAdditive); \ No newline at end of file +extern u32 emuOffset; + +void locateEmuNand(u32 *off, u32 *head, FirmwareSource *emuNand); +void patchEmuNand(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuHeader, u32 branchAdditive); \ No newline at end of file diff --git a/source/fatfs/sdmmc/common.h b/source/fatfs/sdmmc/common.h index 90a327e..3b77ae6 100644 --- a/source/fatfs/sdmmc/common.h +++ b/source/fatfs/sdmmc/common.h @@ -1,4 +1,3 @@ #pragma once -#include #include "../../types.h" \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 61c3ea0..fe7629f 100755 --- a/source/firm.c +++ b/source/firm.c @@ -197,13 +197,13 @@ void main(void) //If we need to boot emuNAND, make sure it exists if(nandType != FIRMWARE_SYSNAND) { - locateEmuNAND(&emuOffset, &emuHeader, &nandType); + locateEmuNand(&emuOffset, &emuHeader, &nandType); if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND; } //Same if we're using emuNAND as the FIRM source else if(firmSource != FIRMWARE_SYSNAND) - locateEmuNAND(&emuOffset, &emuHeader, &firmSource); + locateEmuNand(&emuOffset, &emuHeader, &firmSource); if(!isFirmlaunch) { @@ -287,6 +287,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); + //Find Kernel11 SVC table and free space locations + u8 *freeK11Space; + u32 *arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &freeK11Space); + //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -294,7 +298,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 if(nandType != FIRMWARE_SYSNAND) { u32 branchAdditive = (u32)firm + section[2].offset - (u32)section[2].address; - patchEmuNAND(arm9Section, section[2].size, process9Offset, process9Size, emuOffset, emuHeader, branchAdditive); + patchEmuNand(arm9Section, section[2].size, process9Offset, process9Size, emuHeader, branchAdditive); } //Apply FIRM0/1 writes patches on sysNAND to protect A9LH @@ -310,10 +314,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 patchTitleInstallMinVersionCheck(process9Offset, process9Size); //Restore svcBackdoor - reimplementSvcBackdoor(arm11Section1, section[1].size); + reimplementSvcBackdoor(arm11Section1, arm11SvcTable, &freeK11Space); } - implementSvcGetCFWInfo(arm11Section1, section[1].size); + implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, &freeK11Space); } static inline void patchLegacyFirm(FirmwareType firmType) diff --git a/source/patches.c b/source/patches.c index 6bfc7b8..4cb4ef3 100644 --- a/source/patches.c +++ b/source/patches.c @@ -27,33 +27,6 @@ #include "../build/svcGetCFWInfopatch.h" #include "../build/twl_k11modulespatch.h" -static u32 *arm11SvcTable = NULL; - -static u8 *freeK11Space = NULL; - -static void findArm11SvcTable(u8 *pos, u32 size) -{ - if(arm11SvcTable == NULL) - { - const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; - - u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; - u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch - arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address - while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) - } -} - -static void findFreeK11Space(u8 *pos, u32 size) -{ - if(freeK11Space == NULL) - { - const u8 pattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - freeK11Space = memsearch(pos, pattern, size, 5) + 1; - } -} - u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { u8 *off = memsearch(pos, "ess9", size, 4); @@ -65,6 +38,22 @@ u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; } +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space) +{ + const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; + + u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; + u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch + u32 *arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address + while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) + + const u8 pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + *freeK11Space = memsearch(pos, pattern2, size, 5) + 1; + + return arm11SvcTable; +} + void patchSignatureChecks(u8 *pos, u32 size) { const u16 sigPatch[2] = {0x2000, 0x4770}; @@ -126,40 +115,34 @@ void patchOldFirmWrites(u8 *pos, u32 size) off[1] = writeBlockOld[1]; } -void reimplementSvcBackdoor(u8 *pos, u32 size) +void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space) { //Official implementation of svcBackdoor const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff - 0x0F, 0x1C, 0x81, 0xE3, //orr r1, r1, #0xf00 - 0x28, 0x10, 0x81, 0xE2, //add r1, r1, #0x28 - 0x00, 0x20, 0x91, 0xE5, //ldr r2, [r1] - 0x00, 0x60, 0x22, 0xE9, //stmdb r2!, {sp, lr} - 0x02, 0xD0, 0xA0, 0xE1, //mov sp, r2 - 0x30, 0xFF, 0x2F, 0xE1, //blx r0 - 0x03, 0x00, 0xBD, 0xE8, //pop {r0, r1} - 0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0 - 0x11, 0xFF, 0x2F, 0xE1}; //bx r1 - - findArm11SvcTable(pos, size); + 0x0F, 0x1C, 0x81, 0xE3, //orr r1, r1, #0xf00 + 0x28, 0x10, 0x81, 0xE2, //add r1, r1, #0x28 + 0x00, 0x20, 0x91, 0xE5, //ldr r2, [r1] + 0x00, 0x60, 0x22, 0xE9, //stmdb r2!, {sp, lr} + 0x02, 0xD0, 0xA0, 0xE1, //mov sp, r2 + 0x30, 0xFF, 0x2F, 0xE1, //blx r0 + 0x03, 0x00, 0xBD, 0xE8, //pop {r0, r1} + 0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0 + 0x11, 0xFF, 0x2F, 0xE1}; //bx r1 if(!arm11SvcTable[0x7B]) { - findFreeK11Space(pos, size); + memcpy(*freeK11Space, svcBackdoor, 40); - memcpy(freeK11Space, svcBackdoor, 40); - - arm11SvcTable[0x7B] = 0xFFF00000 + freeK11Space - pos; - freeK11Space += 40; + arm11SvcTable[0x7B] = 0xFFF00000 + *freeK11Space - pos; + (*freeK11Space) += 40; } } -void implementSvcGetCFWInfo(u8 *pos, u32 size) +void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space) { - findFreeK11Space(pos, size); - - memcpy(freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size); + memcpy(*freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size); - CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4); + CFWInfo *info = (CFWInfo *)memsearch(*freeK11Space, "LUMA", svcGetCFWInfo_size, 4); const char *rev = REVISION; bool isRelease; @@ -177,10 +160,8 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size) info->flags = 0 /* master branch */ | ((isRelease ? 1 : 0) << 1) /* is release */; - findArm11SvcTable(pos, size); - - arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //Stubbed svc - freeK11Space += svcGetCFWInfo_size; + arm11SvcTable[0x2E] = 0xFFF00000 + *freeK11Space - pos; //Stubbed svc + (*freeK11Space) += svcGetCFWInfo_size; } void patchTitleInstallMinVersionCheck(u8 *pos, u32 size) diff --git a/source/patches.h b/source/patches.h index 8b6ccae..65a0e7b 100644 --- a/source/patches.h +++ b/source/patches.h @@ -50,12 +50,13 @@ typedef struct __attribute__((packed)) extern bool isN3DS; u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); void patchOldFirmWrites(u8 *pos, u32 size); -void reimplementSvcBackdoor(u8 *pos, u32 size); -void implementSvcGetCFWInfo(u8 *pos, u32 size); +void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); +void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); void patchTwlBg(u8 *pos); \ No newline at end of file