Cleanup, possibly slight speedup by limiting Process9 memsearches to the P9 code
This commit is contained in:
parent
1750b256eb
commit
808c4b7361
@ -185,7 +185,4 @@ void configureCFW(const char *configPath)
|
|||||||
deinitScreens();
|
deinitScreens();
|
||||||
PDN_GPU_CNT = 1;
|
PDN_GPU_CNT = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 t0 = chrono();
|
|
||||||
while(chrono() - t0 < 2 * TICKS_PER_SEC); //wait for 2s
|
|
||||||
}
|
}
|
@ -65,10 +65,10 @@ u32 *getMPU(u8 *pos, u32 size)
|
|||||||
return (u32 *)memsearch(pos, pattern, size, 4);
|
return (u32 *)memsearch(pos, pattern, size, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getEmuCode(u8 *proc9Offset)
|
void *getEmuCode(u8 *pos)
|
||||||
{
|
{
|
||||||
const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
|
const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
|
||||||
|
|
||||||
//Looking for the last free space before Process9
|
//Looking for the last free space before Process9
|
||||||
return memsearch(proc9Offset - 0x3000, pattern, 0x3000, 6) + 0x455;
|
return memsearch(pos + 0x13500, pattern, 0x1000, 6) + 0x455;
|
||||||
}
|
}
|
@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
|
||||||
u32 getSDMMC(u8 *pos, u32 size);
|
u32 getSDMMC(u8 *pos, u32 size);
|
||||||
void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(u8 *pos, u32 size, u32 *readOffset, u32 *writeOffset);
|
||||||
u32 *getMPU(u8 *pos, u32 size);
|
u32 *getMPU(u8 *pos, u32 size);
|
||||||
void *getEmuCode(u8 *proc9Offset);
|
void *getEmuCode(u8 *pos);
|
152
source/firm.c
152
source/firm.c
@ -23,8 +23,6 @@ u32 config,
|
|||||||
firmSource,
|
firmSource,
|
||||||
emuOffset;
|
emuOffset;
|
||||||
|
|
||||||
u64 chronoWhenSplashLoaded = 0;
|
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
u32 bootType,
|
u32 bootType,
|
||||||
@ -36,7 +34,7 @@ void main(void)
|
|||||||
newConfig,
|
newConfig,
|
||||||
emuHeader;
|
emuHeader;
|
||||||
|
|
||||||
startChrono(0); //Start the chronometer. It shouldn't be reset.
|
u64 chronoStarted = 0;
|
||||||
|
|
||||||
//Detect the console being used
|
//Detect the console being used
|
||||||
console = PDN_MPCORE_CFG == 7;
|
console = PDN_MPCORE_CFG == 7;
|
||||||
@ -70,13 +68,17 @@ void main(void)
|
|||||||
u32 pressed = HID_PAD;
|
u32 pressed = HID_PAD;
|
||||||
|
|
||||||
//If no configuration file exists or SELECT is held, load configuration menu
|
//If no configuration file exists or SELECT is held, load configuration menu
|
||||||
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
if(needConfig == 2 || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)))
|
||||||
{
|
{
|
||||||
configureCFW(configPath);
|
configureCFW(configPath);
|
||||||
|
|
||||||
//Zero the last booted FIRM flag
|
//Zero the last booted FIRM flag
|
||||||
CFG_BOOTENV = 0;
|
CFG_BOOTENV = 0;
|
||||||
|
|
||||||
|
chronoStarted = chrono();
|
||||||
|
while(chrono() - chronoStarted < 2 * TICKS_PER_SEC); //Wait for 2s
|
||||||
|
chronoStarted = 1;
|
||||||
|
|
||||||
//Update pressed buttons
|
//Update pressed buttons
|
||||||
pressed = HID_PAD;
|
pressed = HID_PAD;
|
||||||
}
|
}
|
||||||
@ -149,8 +151,8 @@ void main(void)
|
|||||||
loadPayload(pressed);
|
loadPayload(pressed);
|
||||||
|
|
||||||
//If screens are inited or the corresponding option is set, load splash screen
|
//If screens are inited or the corresponding option is set, load splash screen
|
||||||
if(PDN_GPU_CNT != 1 || CONFIG(7)) chronoWhenSplashLoaded = (u64) loadSplash();
|
if((PDN_GPU_CNT != 1 || CONFIG(7)) && loadSplash())
|
||||||
if(chronoWhenSplashLoaded) chronoWhenSplashLoaded = chrono();
|
chronoStarted = chrono();
|
||||||
|
|
||||||
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
||||||
if(pressed & BUTTON_R1)
|
if(pressed & BUTTON_R1)
|
||||||
@ -214,6 +216,12 @@ void main(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(chronoStarted)
|
||||||
|
{
|
||||||
|
while(chronoStarted > 1 && chrono() - chronoStarted < 3 * TICKS_PER_SEC);
|
||||||
|
stopChrono();
|
||||||
|
}
|
||||||
|
|
||||||
launchFirm(!firmType, bootType);
|
launchFirm(!firmType, bootType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +250,6 @@ static inline void loadFirm(u32 firmType, u32 externalFirm)
|
|||||||
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||||
u8 *arm11Section1 = (u8 *)firm + section[1].offset;
|
|
||||||
|
|
||||||
u32 nativeFirmType;
|
u32 nativeFirmType;
|
||||||
|
|
||||||
@ -273,39 +280,41 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
|||||||
nativeFirmType = memcmp(section[2].hash, firm90Hash, 0x10) != 0;
|
nativeFirmType = memcmp(section[2].hash, firm90Hash, 0x10) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nativeFirmType || nandType || a9lhMode == 2)
|
u32 process9Size,
|
||||||
{
|
process9MemAddr;
|
||||||
|
|
||||||
//Find the Process9 NCCH location
|
//Find the Process9 NCCH location
|
||||||
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
|
u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr);
|
||||||
|
|
||||||
//Apply emuNAND patches
|
//Apply emuNAND patches
|
||||||
if(nandType) patchEmuNAND(arm9Section, proc9Offset, emuHeader);
|
if(nandType) patchEmuNAND(arm9Section, process9Offset, process9Size, emuHeader);
|
||||||
|
|
||||||
//Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
|
||||||
if(nativeFirmType || a9lhMode == 2) patchReboots(arm9Section, proc9Offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply FIRM0/1 writes patches on sysNAND to protect A9LH
|
//Apply FIRM0/1 writes patches on sysNAND to protect A9LH
|
||||||
if(a9lhMode && !nandType) patchFirmWrites(arm9Section, 1);
|
else if(a9lhMode) patchFirmWrites(process9Offset, process9Size, 1);
|
||||||
|
|
||||||
|
//Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
|
if(nativeFirmType || a9lhMode == 2) patchReboots(process9Offset, process9Size, process9MemAddr);
|
||||||
|
|
||||||
//Apply signature checks patches
|
//Apply signature checks patches
|
||||||
u32 sigOffset,
|
u32 sigOffset,
|
||||||
sigOffset2;
|
sigOffset2;
|
||||||
|
|
||||||
getSigChecks(arm9Section, section[2].size, &sigOffset, &sigOffset2);
|
getSigChecks(process9Offset, process9Size, &sigOffset, &sigOffset2);
|
||||||
*(u16 *)sigOffset = sigPatch[0];
|
*(u16 *)sigOffset = sigPatch[0];
|
||||||
*(u16 *)sigOffset2 = sigPatch[0];
|
*(u16 *)sigOffset2 = sigPatch[0];
|
||||||
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||||
|
|
||||||
reimplementSvcBackdoor(arm11Section1); //Does nothing if svcBackdoor is still there
|
//Does nothing if svcBackdoor is still there
|
||||||
|
reimplementSvcBackdoor();
|
||||||
|
|
||||||
//Replace the FIRM loader with the injector while copying section0
|
//Replace the FIRM loader with the injector while copying section0
|
||||||
copySection0AndInjectLoader();
|
copySection0AndInjectLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader)
|
static inline void patchEmuNAND(u8 *arm9Section, u8 *process9Offset, u32 process9Size, u32 emuHeader)
|
||||||
{
|
{
|
||||||
//Copy emuNAND code
|
//Copy emuNAND code
|
||||||
void *emuCodeOffset = getEmuCode(proc9Offset);
|
void *emuCodeOffset = getEmuCode(arm9Section);
|
||||||
memcpy(emuCodeOffset, emunand, emunand_size);
|
memcpy(emuCodeOffset, emunand, emunand_size);
|
||||||
|
|
||||||
//Add the data of the found emuNAND
|
//Add the data of the found emuNAND
|
||||||
@ -316,7 +325,7 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader)
|
|||||||
|
|
||||||
//Find and add the SDMMC struct
|
//Find and add the SDMMC struct
|
||||||
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
|
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
|
||||||
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
*pos_sdmmc = getSDMMC(process9Offset, process9Size);
|
||||||
|
|
||||||
//Calculate offset for the hooks
|
//Calculate offset for the hooks
|
||||||
u32 branchOffset = (u32)emuCodeOffset - (u32)firm -
|
u32 branchOffset = (u32)emuCodeOffset - (u32)firm -
|
||||||
@ -326,7 +335,7 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader)
|
|||||||
u32 emuRead,
|
u32 emuRead,
|
||||||
emuWrite;
|
emuWrite;
|
||||||
|
|
||||||
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
getEmuRW(process9Offset, process9Size, &emuRead, &emuWrite);
|
||||||
*(u16 *)emuRead = nandRedir[0];
|
*(u16 *)emuRead = nandRedir[0];
|
||||||
*((u16 *)emuRead + 1) = nandRedir[1];
|
*((u16 *)emuRead + 1) = nandRedir[1];
|
||||||
*((u32 *)emuRead + 1) = branchOffset;
|
*((u32 *)emuRead + 1) = branchOffset;
|
||||||
@ -341,13 +350,12 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader)
|
|||||||
*(mpuOffset + 9) = mpuPatch[2];
|
*(mpuOffset + 9) = mpuPatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset)
|
static inline void patchReboots(u8 *process9Offset, u32 process9Size, u32 process9MemAddr)
|
||||||
{
|
{
|
||||||
//Calculate offset for the firmlaunch code
|
u32 fOpenOffset;
|
||||||
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
|
||||||
|
|
||||||
//Calculate offset for the fOpen function
|
//Calculate offset for the firmlaunch code
|
||||||
u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset);
|
void *rebootOffset = getReboot(process9Offset, process9Size, process9MemAddr, &fOpenOffset);
|
||||||
|
|
||||||
//Copy firmlaunch code
|
//Copy firmlaunch code
|
||||||
memcpy(rebootOffset, reboot, reboot_size);
|
memcpy(rebootOffset, reboot, reboot_size);
|
||||||
@ -357,25 +365,21 @@ static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset)
|
|||||||
*pos_fopen = fOpenOffset;
|
*pos_fopen = fOpenOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reimplementSvcBackdoor(u8 *arm11Section1)
|
static inline void reimplementSvcBackdoor(void)
|
||||||
{
|
{
|
||||||
|
u8 *arm11Section1 = (u8 *)firm + section[1].offset;
|
||||||
|
|
||||||
u32 *exceptionsPage = getExceptionVectorsPage(arm11Section1, section[1].size);
|
u32 *exceptionsPage = getExceptionVectorsPage(arm11Section1, section[1].size);
|
||||||
if(exceptionsPage == NULL) return;
|
|
||||||
|
|
||||||
u32 low24 = (exceptionsPage[2] & 0x00FFFFFF) << 2;
|
u32 offset = (-((exceptionsPage[2] & 0xFFFFFF) << 2) & 0xFFFFF) + 8; //Branch offset + 8 for prefetch
|
||||||
u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension
|
u32 *svcTable = (u32 *)(arm11Section1 + *(u32 *)(arm11Section1 + 0xFFFF0008 - offset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
|
||||||
int offset = (int)(low24 | signMask) + 8; //Branch offset + 8 for prefetch
|
while(*svcTable != 0) svcTable++; //SVC0 = NULL
|
||||||
|
|
||||||
u32* svcTable = (u32 *)(arm11Section1 + *(u32 *)(arm11Section1 + 0xFFFF0008 + offset - 0xFFF00000 + 8) - 0xFFF00000); //svc handler address
|
if(!svcTable[0x7B])
|
||||||
while(*svcTable != 0) svcTable++; //svc0 = NULL
|
{
|
||||||
|
u32 *freeSpace;
|
||||||
|
|
||||||
if(svcTable[0x7B] != 0) return;
|
for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
||||||
|
|
||||||
u32 *freeSpace = exceptionsPage;
|
|
||||||
while(freeSpace < exceptionsPage + 0x400 - 0xA && (freeSpace[0] != 0xFFFFFFFF || freeSpace[1] != 0xFFFFFFFF))
|
|
||||||
freeSpace++;
|
|
||||||
|
|
||||||
if(freeSpace >= exceptionsPage + 0x400 - 0xA) return;
|
|
||||||
|
|
||||||
//Official implementation of svcBackdoor
|
//Official implementation of svcBackdoor
|
||||||
freeSpace[0] = 0xE3CD10FF; //bic r1, sp, #0xff
|
freeSpace[0] = 0xE3CD10FF; //bic r1, sp, #0xff
|
||||||
@ -391,6 +395,7 @@ static inline void reimplementSvcBackdoor(u8 *arm11Section1)
|
|||||||
|
|
||||||
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
|
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void copySection0AndInjectLoader(void)
|
static inline void copySection0AndInjectLoader(void)
|
||||||
{
|
{
|
||||||
@ -403,6 +408,37 @@ static inline void copySection0AndInjectLoader(void)
|
|||||||
memcpy(section[0].address + loaderOffset + injector_size, arm11Section0 + loaderOffset + loaderSize, section[0].size - (loaderOffset + loaderSize));
|
memcpy(section[0].address + loaderOffset + injector_size, arm11Section0 + loaderOffset + loaderSize, section[0].size - (loaderOffset + loaderSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void patchSafeFirm(void)
|
||||||
|
{
|
||||||
|
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
||||||
|
|
||||||
|
if(console)
|
||||||
|
{
|
||||||
|
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
||||||
|
arm9Loader(arm9Section, 0);
|
||||||
|
firm->arm9Entry = (u8 *)0x801B01C;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Apply FIRM0/1 writes patches to protect A9LH
|
||||||
|
patchFirmWrites(arm9Section, section[2].size, console);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patchFirmWrites(u8 *offset, u32 size, u32 mode)
|
||||||
|
{
|
||||||
|
if(mode)
|
||||||
|
{
|
||||||
|
u16 *writeOffset = getFirmWrite(offset, size);
|
||||||
|
*writeOffset = writeBlock[0];
|
||||||
|
*(writeOffset + 1) = writeBlock[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u16 *writeOffset = getFirmWriteSafe(offset, size);
|
||||||
|
*writeOffset = writeBlockSafe[0];
|
||||||
|
*(writeOffset + 1) = writeBlockSafe[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void patchLegacyFirm(u32 firmType)
|
static inline void patchLegacyFirm(u32 firmType)
|
||||||
{
|
{
|
||||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
||||||
@ -451,46 +487,12 @@ static inline void patchLegacyFirm(u32 firmType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void patchSafeFirm(void)
|
|
||||||
{
|
|
||||||
u8 *arm9Section = (u8 *)firm + section[2].offset;
|
|
||||||
|
|
||||||
if(console)
|
|
||||||
{
|
|
||||||
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
|
|
||||||
arm9Loader(arm9Section, 0);
|
|
||||||
firm->arm9Entry = (u8 *)0x801B01C;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply FIRM0/1 writes patches to protect A9LH
|
|
||||||
patchFirmWrites(arm9Section, console);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void patchFirmWrites(u8 *arm9Section, u32 mode)
|
|
||||||
{
|
|
||||||
if(mode)
|
|
||||||
{
|
|
||||||
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
|
||||||
*writeOffset = writeBlock[0];
|
|
||||||
*(writeOffset + 1) = writeBlock[1];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u16 *writeOffset = getFirmWriteSafe(arm9Section, section[2].size);
|
|
||||||
*writeOffset = writeBlockSafe[0];
|
|
||||||
*(writeOffset + 1) = writeBlockSafe[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void launchFirm(u32 firstSectionToCopy, u32 bootType)
|
static inline void launchFirm(u32 firstSectionToCopy, u32 bootType)
|
||||||
{
|
{
|
||||||
//Copy FIRM sections to respective memory locations
|
//Copy FIRM sections to respective memory locations
|
||||||
for(u32 i = firstSectionToCopy; i < 4 && section[i].size; i++)
|
for(u32 i = firstSectionToCopy; i < 4 && section[i].size; i++)
|
||||||
memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size);
|
memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size);
|
||||||
|
|
||||||
while(chronoWhenSplashLoaded && chrono() - chronoWhenSplashLoaded < 3 * TICKS_PER_SEC);
|
|
||||||
stopChrono();
|
|
||||||
|
|
||||||
//Determine the ARM11 entry to use
|
//Determine the ARM11 entry to use
|
||||||
vu32 *arm11;
|
vu32 *arm11;
|
||||||
if(bootType) arm11 = (u32 *)0x1FFFFFFC;
|
if(bootType) arm11 = (u32 *)0x1FFFFFFC;
|
||||||
|
@ -39,11 +39,11 @@ typedef struct patchData {
|
|||||||
|
|
||||||
static inline void loadFirm(u32 firmType, u32 externalFirm);
|
static inline void loadFirm(u32 firmType, u32 externalFirm);
|
||||||
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode);
|
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode);
|
||||||
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader);
|
static inline void patchEmuNAND(u8 *arm9Section, u8 *process9Offset, u32 process9Size, u32 emuHeader);
|
||||||
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset);
|
static inline void patchReboots(u8 *process9Offset, u32 process9Size, u32 process9MemAddr);
|
||||||
static inline void reimplementSvcBackdoor(u8 *arm11Section1);
|
static inline void reimplementSvcBackdoor(void);
|
||||||
static inline void copySection0AndInjectLoader(void);
|
static inline void copySection0AndInjectLoader(void);
|
||||||
static inline void patchLegacyFirm(u32 firmType);
|
|
||||||
static inline void patchSafeFirm(void);
|
static inline void patchSafeFirm(void);
|
||||||
static void patchFirmWrites(u8 *arm9Section, u32 mode);
|
static void patchFirmWrites(u8 *offset, u32 size, u32 mode);
|
||||||
|
static inline void patchLegacyFirm(u32 firmType);
|
||||||
static inline void launchFirm(u32 firstSectionToCopy, u32 bootType);
|
static inline void launchFirm(u32 firstSectionToCopy, u32 bootType);
|
@ -20,9 +20,15 @@ const u16 nandRedir[2] = {0x4C00, 0x47A0},
|
|||||||
* Functions
|
* Functions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
u8 *getProc9(u8 *pos, u32 size)
|
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||||
{
|
{
|
||||||
return memsearch(pos, "ess9", size, 4);
|
u8 *off = memsearch(pos, "ess9", size, 4);
|
||||||
|
|
||||||
|
*process9Size = *(u32 *)(off - 0x100) * 0x200;
|
||||||
|
*process9MemAddr = *(u32 *)(off + 0xC);
|
||||||
|
|
||||||
|
//Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
|
||||||
|
return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2)
|
void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2)
|
||||||
@ -35,24 +41,17 @@ void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2)
|
|||||||
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1;
|
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getReboot(u8 *pos, u32 size)
|
void *getReboot(u8 *pos, u32 size, u32 process9MemAddr, u32 *fOpenOffset)
|
||||||
{
|
{
|
||||||
//Look for FIRM reboot code
|
//Look for FIRM reboot code
|
||||||
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
||||||
|
|
||||||
return memsearch(pos, pattern, size, 4) - 0x10;
|
u8 *off = memsearch(pos, pattern, size, 4) - 0x10;
|
||||||
}
|
|
||||||
|
|
||||||
u32 getfOpen(u8 *proc9Offset, void *rebootOffset)
|
|
||||||
{
|
|
||||||
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
|
||||||
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
|
||||||
|
|
||||||
//Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
|
|
||||||
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
|
||||||
|
|
||||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||||
return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr;
|
*fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & 0xFFFFF) - pos + process9MemAddr);
|
||||||
|
|
||||||
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 *getFirmWrite(u8 *pos, u32 size)
|
u16 *getFirmWrite(u8 *pos, u32 size)
|
||||||
@ -91,7 +90,7 @@ u32 getLoader(u8 *pos, u32 *loaderSize)
|
|||||||
|
|
||||||
u32 *getExceptionVectorsPage(u8 *pos, u32 size)
|
u32 *getExceptionVectorsPage(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
const u8 pattern[] = {0x00,0xB0,0x9C,0xE5,0x0A,0xB0,0x0B,0xE0,0x0A,0x00,0x5B,0xE1,0xFB,0xFF,0xFF,0x1A};
|
const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||||
|
|
||||||
return (u32 *)(memsearch(pos, pattern, size, 16) - 0x2C);
|
return (u32 *)(memsearch(pos, pattern, size, 4) - 0x2C);
|
||||||
}
|
}
|
@ -18,12 +18,10 @@ const u16 nandRedir[2],
|
|||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
u8 *getProc9(u8 *pos, u32 size);
|
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||||
void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2);
|
void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2);
|
||||||
void *getReboot(u8 *pos, u32 size);
|
void *getReboot(u8 *pos, u32 size, u32 process9MemAddr, u32 *fOpenOffset);
|
||||||
u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
|
|
||||||
u16 *getFirmWrite(u8 *pos, u32 size);
|
u16 *getFirmWrite(u8 *pos, u32 size);
|
||||||
u16 *getFirmWriteSafe(u8 *pos, u32 size);
|
u16 *getFirmWriteSafe(u8 *pos, u32 size);
|
||||||
|
|
||||||
u32 getLoader(u8 *pos, u32 *loaderSize);
|
u32 getLoader(u8 *pos, u32 *loaderSize);
|
||||||
u32* getExceptionVectorsPage(u8 *pos, u32 size); //Multi-purpose, don't change
|
u32 *getExceptionVectorsPage(u8 *pos, u32 size);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
|
||||||
|
u32 chronoStarted = 0;
|
||||||
|
|
||||||
u32 waitInput(void)
|
u32 waitInput(void)
|
||||||
{
|
{
|
||||||
u32 pressedKey = 0,
|
u32 pressedKey = 0,
|
||||||
@ -44,23 +46,27 @@ void startChrono(u64 initialTicks)
|
|||||||
{
|
{
|
||||||
//Based on a NATIVE_FIRM disassembly
|
//Based on a NATIVE_FIRM disassembly
|
||||||
|
|
||||||
*(vu16 *)(0x10003002 + 4 * 0) = 0; //67MHz
|
*(vu16 *)0x10003002 = 0; //67MHz
|
||||||
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 4; //Count-up
|
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 4; //Count-up
|
||||||
|
|
||||||
for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i));
|
for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i));
|
||||||
|
|
||||||
*(vu16 *)(0x10003002 + 4 * 0) = 0x80; //67MHz; enabled
|
*(vu16 *)0x10003002 = 0x80; //67MHz; enabled
|
||||||
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled
|
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 chrono(void)
|
u64 chrono(void)
|
||||||
{
|
{
|
||||||
|
if(!chronoStarted) startChrono(0);
|
||||||
|
|
||||||
u64 res = 0;
|
u64 res = 0;
|
||||||
|
|
||||||
for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i);
|
for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopChrono(void)
|
void stopChrono(void)
|
||||||
{
|
{
|
||||||
for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) &= ~0x80;
|
if(chronoStarted) for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) &= ~0x80;
|
||||||
}
|
}
|
Reference in New Issue
Block a user