Cleanup and refactoring
This commit is contained in:
parent
ad9e00acaa
commit
8209433696
@ -25,12 +25,12 @@
|
|||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
#include "../build/emunandpatch.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];
|
static u8 temp[0x200];
|
||||||
|
|
||||||
const u32 nandSize = getMMCDevice(0)->total_size;
|
const u32 nandSize = getMMCDevice(0)->total_size;
|
||||||
u32 nandOffset = *emuNAND == FIRMWARE_EMUNAND ? 0 :
|
u32 nandOffset = *emuNand == FIRMWARE_EMUNAND ? 0 :
|
||||||
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
||||||
|
|
||||||
//Check for RedNAND
|
//Check for RedNAND
|
||||||
@ -53,12 +53,12 @@ void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND)
|
|||||||
or to SysNAND if there isn't any */
|
or to SysNAND if there isn't any */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*emuNAND = (*emuNAND == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND;
|
*emuNand = (*emuNand == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND;
|
||||||
if(*emuNAND) locateEmuNAND(off, head, emuNAND);
|
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};
|
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;
|
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
|
//Look for struct code
|
||||||
const u8 pattern[] = {0x21, 0x20, 0x18, 0x20};
|
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);
|
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};
|
const u16 nandRedir[2] = {0x4C00, 0x47A0};
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset)
|
|||||||
((u32 *)writeOffset)[1] = 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};
|
const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
|
||||||
|
|
||||||
@ -107,26 +107,26 @@ static inline void patchMPU(u8 *pos, u32 size)
|
|||||||
off[9] = mpuPatch[2];
|
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
|
//Copy emuNAND code
|
||||||
void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize);
|
void *freeK9Space = getFreeK9Space(arm9Section, arm9SectionSize);
|
||||||
memcpy(emuCodeOffset, emunand, emunand_size);
|
memcpy(freeK9Space, emunand, emunand_size);
|
||||||
|
|
||||||
//Add the data of the found emuNAND
|
//Add the data of the found emuNAND
|
||||||
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4),
|
u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_size, 4),
|
||||||
*pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
*posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_size, 4);
|
||||||
*pos_offset = emuOffset;
|
*posOffset = emuOffset;
|
||||||
*pos_header = emuHeader;
|
*posHeader = emuHeader;
|
||||||
|
|
||||||
//Find and add the SDMMC struct
|
//Find and add the SDMMC struct
|
||||||
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
|
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_size, 4);
|
||||||
*pos_sdmmc = getSDMMC(process9Offset, process9Size);
|
*posSdmmc = getSdmmc(process9Offset, process9Size);
|
||||||
|
|
||||||
//Add emuNAND hooks
|
//Add emuNAND hooks
|
||||||
u32 branchOffset = (u32)emuCodeOffset - branchAdditive;
|
u32 branchOffset = (u32)freeK9Space - branchAdditive;
|
||||||
patchNANDRW(process9Offset, process9Size, branchOffset);
|
patchNandRw(process9Offset, process9Size, branchOffset);
|
||||||
|
|
||||||
//Set MPU for emu code region
|
//Set MPU for emu code region
|
||||||
patchMPU(arm9Section, arm9SectionSize);
|
patchMpu(arm9Section, arm9SectionSize);
|
||||||
}
|
}
|
@ -26,5 +26,7 @@
|
|||||||
|
|
||||||
#define NCSD_MAGIC 0x4453434E
|
#define NCSD_MAGIC 0x4453434E
|
||||||
|
|
||||||
void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND);
|
extern u32 emuOffset;
|
||||||
void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuOffset, u32 emuHeader, u32 branchAdditive);
|
|
||||||
|
void locateEmuNand(u32 *off, u32 *head, FirmwareSource *emuNand);
|
||||||
|
void patchEmuNand(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuHeader, u32 branchAdditive);
|
@ -1,4 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "../../types.h"
|
#include "../../types.h"
|
@ -197,13 +197,13 @@ void main(void)
|
|||||||
//If we need to boot emuNAND, make sure it exists
|
//If we need to boot emuNAND, make sure it exists
|
||||||
if(nandType != FIRMWARE_SYSNAND)
|
if(nandType != FIRMWARE_SYSNAND)
|
||||||
{
|
{
|
||||||
locateEmuNAND(&emuOffset, &emuHeader, &nandType);
|
locateEmuNand(&emuOffset, &emuHeader, &nandType);
|
||||||
if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND;
|
if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Same if we're using emuNAND as the FIRM source
|
//Same if we're using emuNAND as the FIRM source
|
||||||
else if(firmSource != FIRMWARE_SYSNAND)
|
else if(firmSource != FIRMWARE_SYSNAND)
|
||||||
locateEmuNAND(&emuOffset, &emuHeader, &firmSource);
|
locateEmuNand(&emuOffset, &emuHeader, &firmSource);
|
||||||
|
|
||||||
if(!isFirmlaunch)
|
if(!isFirmlaunch)
|
||||||
{
|
{
|
||||||
@ -287,6 +287,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
process9MemAddr;
|
process9MemAddr;
|
||||||
u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &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
|
//Apply signature patches
|
||||||
patchSignatureChecks(process9Offset, process9Size);
|
patchSignatureChecks(process9Offset, process9Size);
|
||||||
|
|
||||||
@ -294,7 +298,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32
|
|||||||
if(nandType != FIRMWARE_SYSNAND)
|
if(nandType != FIRMWARE_SYSNAND)
|
||||||
{
|
{
|
||||||
u32 branchAdditive = (u32)firm + section[2].offset - (u32)section[2].address;
|
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
|
//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);
|
patchTitleInstallMinVersionCheck(process9Offset, process9Size);
|
||||||
|
|
||||||
//Restore svcBackdoor
|
//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)
|
static inline void patchLegacyFirm(FirmwareType firmType)
|
||||||
|
@ -27,33 +27,6 @@
|
|||||||
#include "../build/svcGetCFWInfopatch.h"
|
#include "../build/svcGetCFWInfopatch.h"
|
||||||
#include "../build/twl_k11modulespatch.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 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||||
{
|
{
|
||||||
u8 *off = memsearch(pos, "ess9", size, 4);
|
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;
|
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)
|
void patchSignatureChecks(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
const u16 sigPatch[2] = {0x2000, 0x4770};
|
const u16 sigPatch[2] = {0x2000, 0x4770};
|
||||||
@ -126,7 +115,7 @@ void patchOldFirmWrites(u8 *pos, u32 size)
|
|||||||
off[1] = writeBlockOld[1];
|
off[1] = writeBlockOld[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void reimplementSvcBackdoor(u8 *pos, u32 size)
|
void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space)
|
||||||
{
|
{
|
||||||
//Official implementation of svcBackdoor
|
//Official implementation of svcBackdoor
|
||||||
const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff
|
const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff
|
||||||
@ -140,26 +129,20 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
|||||||
0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0
|
0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0
|
||||||
0x11, 0xFF, 0x2F, 0xE1}; //bx r1
|
0x11, 0xFF, 0x2F, 0xE1}; //bx r1
|
||||||
|
|
||||||
findArm11SvcTable(pos, size);
|
|
||||||
|
|
||||||
if(!arm11SvcTable[0x7B])
|
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;
|
const char *rev = REVISION;
|
||||||
bool isRelease;
|
bool isRelease;
|
||||||
@ -177,10 +160,8 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size)
|
|||||||
|
|
||||||
info->flags = 0 /* master branch */ | ((isRelease ? 1 : 0) << 1) /* is release */;
|
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)
|
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size)
|
||||||
|
@ -50,12 +50,13 @@ typedef struct __attribute__((packed))
|
|||||||
extern bool isN3DS;
|
extern bool isN3DS;
|
||||||
|
|
||||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
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 patchSignatureChecks(u8 *pos, u32 size);
|
||||||
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size);
|
void patchTitleInstallMinVersionCheck(u8 *pos, u32 size);
|
||||||
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
||||||
void patchFirmWrites(u8 *pos, u32 size);
|
void patchFirmWrites(u8 *pos, u32 size);
|
||||||
void patchOldFirmWrites(u8 *pos, u32 size);
|
void patchOldFirmWrites(u8 *pos, u32 size);
|
||||||
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space);
|
||||||
void implementSvcGetCFWInfo(u8 *pos, u32 size);
|
void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space);
|
||||||
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType);
|
||||||
void patchTwlBg(u8 *pos);
|
void patchTwlBg(u8 *pos);
|
Reference in New Issue
Block a user