diff --git a/injector/source/patcher.c b/injector/source/patcher.c index cfd63d8..587d83c 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -363,16 +363,13 @@ void patchCode(u64 progId, u8 *code, u32 size) static const u8 fpdVerPattern[] = { 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01 }; + + static const u8 mostRecentFpdVer = 0x06; + + u8 *fpdVer = memsearch(code, fpdVerPattern, size, sizeof(fpdVerPattern)); - static const u8 fpdVerPatch = 0x06; - - //Allow online access to work with old friends modules - patchMemory(code, size, - fpdVerPattern, - sizeof(fpdVerPattern), 9, - &fpdVerPatch, - sizeof(fpdVerPatch), 1 - ); + //Allow online access to work with old friends modules, without breaking newer firmwares + if(fpdVer != NULL && fpdVer[9] < mostRecentFpdVer) fpdVer[9] = mostRecentFpdVer; break; } diff --git a/source/config.c b/source/config.c index ae72eb2..743bb24 100644 --- a/source/config.c +++ b/source/config.c @@ -186,7 +186,4 @@ void configureCFW(const char *configPath) deinitScreens(); PDN_GPU_CNT = 1; } - - u64 t0 = chrono(); - while(chrono() - t0 < 2 * TICKS_PER_SEC); //wait for 2s } diff --git a/source/emunand.c b/source/emunand.c index 26e0f53..7aa8ad1 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -48,13 +48,13 @@ u32 getSDMMC(u8 *pos, u32 size) return *(u32 *)(off + 9) + *(u32 *)(off + 0xD); } -void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff) +void getEmuRW(u8 *pos, u32 size, u32 *readOffset, u32 *writeOffset) { //Look for read/write code const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05}; - *readOff = (u32)memsearch(pos, pattern, size, 4) - 6; - *writeOff = (u32)memsearch((u8 *)(*readOff + 0xA), pattern, 0x100, 4) - 6; + *readOffset = (u32)memsearch(pos, pattern, size, 4) - 6; + *writeOffset = (u32)memsearch((u8 *)(*readOffset + 0xA), pattern, 0x100, 4) - 6; } u32 *getMPU(u8 *pos, u32 size) @@ -65,10 +65,10 @@ u32 *getMPU(u8 *pos, u32 size) return (u32 *)memsearch(pos, pattern, size, 4); } -void *getEmuCode(u8 *proc9Offset) +void *getEmuCode(u8 *pos) { const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; //Looking for the last free space before Process9 - return memsearch(proc9Offset - 0x3000, pattern, 0x3000, 6) + 0x455; + return memsearch(pos + 0x13500, pattern, 0x1000, 6) + 0x455; } \ No newline at end of file diff --git a/source/emunand.h b/source/emunand.h index 2d5e98a..f992269 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -10,6 +10,6 @@ void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND); 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); -void *getEmuCode(u8 *proc9Offset); \ No newline at end of file +void *getEmuCode(u8 *pos); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index f0952b1..a6da9eb 100755 --- a/source/firm.c +++ b/source/firm.c @@ -24,8 +24,6 @@ u32 config, firmSource, emuOffset; -u64 chronoWhenSplashLoaded = 0; - static inline void patchExceptionHandlersInstall(u8 *arm9Section) { static const u8 pattern[] = { @@ -71,8 +69,8 @@ void main(void) needConfig, newConfig, emuHeader; - - startChrono(0); //Start the chronometer. It shouldn't be reset. + + u64 chronoStarted = 0; //Detect the console being used console = PDN_MPCORE_CFG == 7; @@ -106,13 +104,17 @@ void main(void) u32 pressed = HID_PAD; //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); //Zero the last booted FIRM flag CFG_BOOTENV = 0; + chronoStarted = chrono(); + while(chrono() - chronoStarted < 2 * TICKS_PER_SEC); //Wait for 2s + chronoStarted = 1; + //Update pressed buttons pressed = HID_PAD; } @@ -193,9 +195,9 @@ void main(void) loadPayload(pressed); //If screens are inited or the corresponding option is set, load splash screen - if(PDN_GPU_CNT != 1 || CONFIG(8)) chronoWhenSplashLoaded = (u64) loadSplash(); - if(chronoWhenSplashLoaded) chronoWhenSplashLoaded = chrono(); - + if((PDN_GPU_CNT != 1 || CONFIG(8)) && loadSplash()) + chronoStarted = chrono(); + //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one if(pressed & BUTTON_R1) { @@ -260,6 +262,12 @@ void main(void) break; } + if(chronoStarted) + { + while(chronoStarted > 1 && chrono() - chronoStarted < 3 * TICKS_PER_SEC); + stopChrono(); + } + launchFirm(!firmType, bootType); } @@ -301,7 +309,6 @@ static inline void patchKernelFCRAMAndVRAMMappingPermissions(u8* arm11Section1) static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) { u8 *arm9Section = (u8 *)firm + section[2].offset; - u8 *arm11Section1 = (u8 *)firm + section[1].offset; u32 nativeFirmType; @@ -332,29 +339,32 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) nativeFirmType = memcmp(section[2].hash, firm90Hash, 0x10) != 0; } - if(nativeFirmType || nandType || a9lhMode == 2) - { - //Find the Process9 NCCH location - u8 *proc9Offset = getProc9(arm9Section, section[2].size); + u32 process9Size, + process9MemAddr; - //Apply emuNAND patches - if(nandType) patchEmuNAND(arm9Section, proc9Offset, emuHeader); + //Find the Process9 NCCH location + u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); - //Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax - if(nativeFirmType || a9lhMode == 2) patchReboots(arm9Section, proc9Offset); - } + //Apply emuNAND patches + if(nandType) patchEmuNAND(arm9Section, process9Offset, process9Size, emuHeader); //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 - u32 sigOffset, - sigOffset2; + u16 *sigOffset, + *sigOffset2; - getSigChecks(arm9Section, section[2].size, &sigOffset, &sigOffset2); - *(u16 *)sigOffset = sigPatch[0]; - *(u16 *)sigOffset2 = sigPatch[0]; - *((u16 *)sigOffset2 + 1) = sigPatch[1]; + getSigChecks(process9Offset, process9Size, &sigOffset, &sigOffset2); + *sigOffset = sigPatch[0]; + sigOffset2[0] = sigPatch[0]; + sigOffset2[1] = sigPatch[1]; + + //Does nothing if svcBackdoor is still there + reimplementSvcBackdoor(); if(CONFIG(5)) { @@ -365,16 +375,14 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode) //Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1); } - - reimplementSvcBackdoor(arm11Section1); //Does nothing if svcBackdoor is still there //Replace the FIRM loader with the injector while copying section0 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 - void *emuCodeOffset = getEmuCode(proc9Offset); + void *emuCodeOffset = getEmuCode(arm9Section); memcpy(emuCodeOffset, emunand, emunand_size); //Add the data of the found emuNAND @@ -385,7 +393,7 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader) //Find and add the SDMMC struct 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 u32 branchOffset = (u32)emuCodeOffset - (u32)firm - @@ -395,7 +403,7 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader) u32 emuRead, emuWrite; - getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite); + getEmuRW(process9Offset, process9Size, &emuRead, &emuWrite); *(u16 *)emuRead = nandRedir[0]; *((u16 *)emuRead + 1) = nandRedir[1]; *((u32 *)emuRead + 1) = branchOffset; @@ -410,13 +418,12 @@ static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader) *(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 - void *rebootOffset = getReboot(arm9Section, section[2].size); + u32 fOpenOffset; - //Calculate offset for the fOpen function - u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset); + //Calculate offset for the firmlaunch code + void *rebootOffset = getReboot(process9Offset, process9Size, process9MemAddr, &fOpenOffset); //Copy firmlaunch code memcpy(rebootOffset, reboot, reboot_size); @@ -426,39 +433,24 @@ static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset) *pos_fopen = fOpenOffset; } -static inline void reimplementSvcBackdoor(u8 *arm11Section1) +static inline void reimplementSvcBackdoor(void) { - u32 *exceptionsPage = getExceptionVectorsPage(arm11Section1, section[1].size); - if(exceptionsPage == NULL) return; - - u32 low24 = (exceptionsPage[2] & 0x00FFFFFF) << 2; - u32 signMask = (u32)(-(low24 >> 25)) & 0xFC000000; //Sign extension - int offset = (int)(low24 | signMask) + 8; //Branch offset + 8 for prefetch - - u32* svcTable = (u32 *)(arm11Section1 + *(u32 *)(arm11Section1 + 0xFFFF0008 + offset - 0xFFF00000 + 8) - 0xFFF00000); //svc handler address - while(*svcTable != 0) svcTable++; //svc0 = NULL - - if(svcTable[0x7B] != 0) return; - - 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 - freeSpace[0] = 0xE3CD10FF; //bic r1, sp, #0xff - freeSpace[1] = 0xE3811C0F; //orr r1, r1, #0xf00 - freeSpace[2] = 0xE2811028; //add r1, r1, #0x28 - freeSpace[3] = 0xE5912000; //ldr r2, [r1] - freeSpace[4] = 0xE9226000; //stmdb r2!, {sp, lr} - freeSpace[5] = 0xE1A0D002; //mov sp, r2 - freeSpace[6] = 0xE12FFF30; //blx r0 - freeSpace[7] = 0xE8BD0003; //pop {r0, r1} - freeSpace[8] = 0xE1A0D000; //mov sp, r0 - freeSpace[9] = 0xE12FFF11; //bx r1 - - svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *) exceptionsPage); + u8 *arm11Section1 = (u8 *)firm + section[1].offset; + + u32 *exceptionsPage; + + u32 *svcTable = getSvcAndExceptions(arm11Section1, section[1].size, &exceptionsPage); + + if(!svcTable[0x7B]) + { + u32 *freeSpace; + + for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++); + + memcpy(freeSpace, svcBackdoor, 40); + + svcTable[0x7B] = 0xFFFF0000 + (u32)((u8 *)freeSpace - (u8 *)exceptionsPage); + } } static inline void copySection0AndInjectLoader(void) @@ -472,6 +464,37 @@ static inline void copySection0AndInjectLoader(void) 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) { //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader @@ -520,46 +543,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 sectionNum, u32 bootType) { //Copy FIRM sections to respective memory locations - for(u32 i = firstSectionToCopy; i < 4 && section[i].size; i++) - memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size); + for(; sectionNum < 4 && section[sectionNum].size; sectionNum++) + memcpy(section[sectionNum].address, (u8 *)firm + section[sectionNum].offset, section[sectionNum].size); - while(chronoWhenSplashLoaded && chrono() - chronoWhenSplashLoaded < 3 * TICKS_PER_SEC); - stopChrono(); - //Determine the ARM11 entry to use vu32 *arm11; if(bootType) arm11 = (u32 *)0x1FFFFFFC; @@ -574,4 +563,4 @@ static inline void launchFirm(u32 firstSectionToCopy, u32 bootType) //Final jump to ARM9 kernel ((void (*)())firm->arm9Entry)(); -} +} \ No newline at end of file diff --git a/source/firm.h b/source/firm.h index 5ef2549..a4e567f 100644 --- a/source/firm.h +++ b/source/firm.h @@ -39,11 +39,11 @@ typedef struct patchData { static inline void loadFirm(u32 firmType, u32 externalFirm); static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode); -static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader); -static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset); -static inline void reimplementSvcBackdoor(u8 *arm11Section1); +static inline void patchEmuNAND(u8 *arm9Section, u8 *process9Offset, u32 process9Size, u32 emuHeader); +static inline void patchReboots(u8 *process9Offset, u32 process9Size, u32 process9MemAddr); +static inline void reimplementSvcBackdoor(void); static inline void copySection0AndInjectLoader(void); -static inline void patchLegacyFirm(u32 firmType); static inline void patchSafeFirm(void); -static void patchFirmWrites(u8 *arm9Section, u32 mode); -static inline void launchFirm(u32 firstSectionToCopy, u32 bootType); \ No newline at end of file +static void patchFirmWrites(u8 *offset, u32 size, u32 mode); +static inline void patchLegacyFirm(u32 firmType); +static inline void launchFirm(u32 sectionNum, u32 bootType); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 5c3fda1..1efa708 100644 --- a/source/patches.c +++ b/source/patches.c @@ -18,43 +18,54 @@ const u16 nandRedir[2] = {0x4C00, 0x47A0}, const u8 unitInfoPatch = 0xE3; +//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 + /************************************************** * 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 - 0x60) * 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, u16 **off, u16 **off2) { //Look for signature checks const u8 pattern[] = {0xC0, 0x1C, 0x76, 0xE7}, pattern2[] = {0xB5, 0x22, 0x4D, 0x0C}; - *off = (u32)memsearch(pos, pattern, size, 4); - *off2 = (u32)memsearch(pos, pattern2, size, 4) - 1; + *off = (u16 *)memsearch(pos, pattern, size, 4); + *off2 = (u16 *)(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 const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2}; - return 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; + u8 *off = memsearch(pos, pattern, size, 4) - 0x10; //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) & (0xFFFFFF << 2)) - pos + process9MemAddr); + + return off; } u16 *getFirmWrite(u8 *pos, u32 size) @@ -99,9 +110,15 @@ u32 getLoader(u8 *pos, u32 *loaderSize) return (u32)(off - pos); } -u32* getExceptionVectorsPage(u8 *pos, u32 size) +u32 *getSvcAndExceptions(u8 *pos, u32 size, u32 **exceptionsPage) { - 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}; //cpsid aif - return (u32 *)(memsearch(pos, pattern, size, 16) - 0x2C); -} + *exceptionsPage = (u32 *)(memsearch(pos, pattern, size, 4) - 0x2C); + + u32 svcOffset = (-(((*exceptionsPage)[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch + u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address + while(*svcTable) svcTable++; //Look for SVC0 (NULL) + + return svcTable; +} \ No newline at end of file diff --git a/source/patches.h b/source/patches.h index 6cff947..aa47464 100644 --- a/source/patches.h +++ b/source/patches.h @@ -15,17 +15,16 @@ const u16 nandRedir[2], writeBlock[2], writeBlockSafe[2]; const u8 unitInfoPatch; +const u8 svcBackdoor[40]; /************************************************** * Functions **************************************************/ -u8 *getProc9(u8 *pos, u32 size); -void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2); -void *getReboot(u8 *pos, u32 size); -u32 getfOpen(u8 *proc9Offset, void *rebootOffset); +u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); +void getSigChecks(u8 *pos, u32 size, u16 **off, u16 **off2); +void *getReboot(u8 *pos, u32 size, u32 process9MemAddr, u32 *fOpenOffset); u16 *getFirmWrite(u8 *pos, u32 size); u16 *getFirmWriteSafe(u8 *pos, u32 size); u8 *getUnitInfoValueSet(u8 *pos, u32 size); - u32 getLoader(u8 *pos, u32 *loaderSize); -u32* getExceptionVectorsPage(u8 *pos, u32 size); //Multi-purpose, don't change +u32 *getSvcAndExceptions(u8 *pos, u32 size, u32 **exceptionsPage); \ No newline at end of file diff --git a/source/utils.c b/source/utils.c index 5c10112..5d565c6 100644 --- a/source/utils.c +++ b/source/utils.c @@ -40,23 +40,33 @@ void mcuReboot(void) } //TODO: add support for TIMER IRQ -void startChrono(u64 initialTicks) +static void startChrono(u64 initialTicks) { //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 = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i)); - - *(vu16 *)(0x10003002 + 4 * 0) = 0x80; //67MHz; enabled + + for(u32 i = 0; i < 4; i++) *(vu16 *)(0x10003000 + 4 * i) = (u16)(initialTicks >> (16 * i)); + + *(vu16 *)0x10003002 = 0x80; //67MHz; enabled for(u32 i = 1; i < 4; i++) *(vu16 *)(0x10003002 + 4 * i) = 0x84; //Count-up; enabled } u64 chrono(void) { + static u32 chronoStarted = 0; + + if(!chronoStarted) + { + startChrono(0); + chronoStarted++; + } + u64 res = 0; + for(u32 i = 0; i < 4; i++) res |= *(vu16 *)(0x10003000 + 4 * i) << (16 * i); + return res; } diff --git a/source/utils.h b/source/utils.h index e2ef8ff..b6c78ee 100644 --- a/source/utils.h +++ b/source/utils.h @@ -11,6 +11,5 @@ void mcuReboot(void); #define TICKS_PER_SEC 67027964ULL -void startChrono(u64 initialTicks); u64 chrono(void); void stopChrono(void); \ No newline at end of file