From 3475cfe1e6ac2297c2bfd603b66a93209849554a Mon Sep 17 00:00:00 2001 From: Aurora Date: Sat, 2 Apr 2016 17:58:06 +0200 Subject: [PATCH] Changed indentation style across the code to make it more readable, added newlines before comments, moved patches to separate functions, made memory operations slightly faster by compiling them with O3 (thanks TuxSH!) --- Makefile | 2 + injector/source/patcher.c | 52 +++++++---- loader/Makefile | 2 +- loader/source/main.c | 7 +- loader/source/start.s | 5 +- screeninit/Makefile | 2 +- screeninit/source/main.c | 4 +- screeninit/source/start.s | 5 +- source/crypto.c | 22 +++-- source/draw.c | 39 ++++++--- source/emunand.c | 30 ++++--- source/firm.c | 179 +++++++++++++++++++++++--------------- source/fs.c | 21 +++-- source/i2c.c | 42 ++++++--- source/loader.c | 6 +- source/main.c | 3 +- source/memory.c | 22 +++-- source/patches.c | 19 ++-- source/screeninit.c | 20 +++-- source/start.s | 5 +- source/utils.c | 32 ++++--- 21 files changed, 333 insertions(+), 186 deletions(-) diff --git a/Makefile b/Makefile index 303566f..1a9fad3 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,8 @@ $(dir_build)/main.elf: $(objects_cfw) # FatFs requires libgcc for __aeabi_uidiv $(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^ +$(dir_build)/memory.o : CFLAGS+=-O3 + $(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/patches.h $(dir_build)/loader.h $(dir_build)/screeninit.h @mkdir -p "$(@D)" $(COMPILE.c) $(OUTPUT_OPTION) $< diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 36f1b4f..5410956 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -11,7 +11,8 @@ static u32 config = 0; static u8 secureinfo[0x111] = {0}; //Quick Search algorithm, adapted from http://igm.univ-mlv.fr/~lecroq/string/node19.html#SECTION00190 -static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize){ +static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize) +{ const u8 *patternc = (const u8 *)pattern; //Preprocessing @@ -25,7 +26,8 @@ static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSiz //Searching u32 j = 0; - while(j <= size - patternSize){ + while(j <= size - patternSize) + { if(memcmp(patternc, startPos + j, patternSize) == 0) return startPos + j; j += table[startPos[j + patternSize]]; @@ -34,11 +36,14 @@ static u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSiz return NULL; } -static u32 patch_memory(u8 *start, u32 size, const void *pattern, u32 patsize, int offset, const void *replace, u32 repsize, u32 count){ +static u32 patch_memory(u8 *start, u32 size, const void *pattern, u32 patsize, int offset, const void *replace, u32 repsize, u32 count) +{ u32 i; - for(i = 0; i < count; i++){ + for(i = 0; i < count; i++) + { u8 *found = memsearch(start, pattern, size, patsize); + if(found == NULL) break; @@ -55,7 +60,8 @@ static u32 patch_memory(u8 *start, u32 size, const void *pattern, u32 patsize, i return i; } -static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags){ +static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags) +{ FS_Archive archive; FS_Path ppath; @@ -70,7 +76,8 @@ static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags){ return IFile_Open(file, archive, ppath, flags); } -static int load_secureinfo(){ +static int load_secureinfo() +{ IFile file; Result ret; u64 total; @@ -79,7 +86,8 @@ static int load_secureinfo(){ return 0; ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ); - if(R_SUCCEEDED(ret)){ + if(R_SUCCEEDED(ret)) + { ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo)); IFile_Close(&file); if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)) @@ -89,7 +97,8 @@ static int load_secureinfo(){ return ret; } -static int load_config(){ +static int load_config() +{ IFile file; Result ret; u64 total; @@ -98,7 +107,8 @@ static int load_config(){ return 0; ret = file_open(&file, ARCHIVE_SDMC, "/aurei/config.bin", FS_OPEN_READ); - if(R_SUCCEEDED(ret)){ + if(R_SUCCEEDED(ret)) + { ret = IFile_Read(&file, &total, (void *)&config, 3); IFile_Close(&file); } @@ -106,9 +116,10 @@ static int load_config(){ return ret; } -u32 patch_code(u64 progid, u8 *code, u32 size){ - switch(progid){ - +u32 patch_code(u64 progid, u8 *code, u32 size) +{ + switch(progid) + { case 0x0004003000008F02LL: // USA Menu case 0x0004003000008202LL: // EUR Menu case 0x0004003000009802LL: // JPN Menu @@ -129,6 +140,7 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ regionFreePatch, sizeof(regionFreePatch), 1 ); + break; } @@ -160,7 +172,8 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ sizeof(blockEShopUpdateCheckPatch), 1 ); - if(R_SUCCEEDED(load_secureinfo())){ + if(R_SUCCEEDED(load_secureinfo())) + { static const char countryRespPattern[] = { 0x01, 0x20, 0x01, 0x90, 0x22, 0x46, 0x06, 0x9B }; @@ -171,7 +184,8 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ const char *country; char countryRespPatch[sizeof(countryRespPatchModel)]; - switch(secureinfo[0x100]){ + switch(secureinfo[0x100]) + { case 1: country = "US"; break; case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this case 3: country = "AU"; break; @@ -194,6 +208,7 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ sizeof(countryRespPatch), 1 ); } + break; } @@ -204,7 +219,8 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ case 0x0004001000027000LL: // KOR MSET case 0x0004001000028000LL: // TWN MSET { - if(R_SUCCEEDED(load_config()) && ((config >> 5) & 1)){ + if(R_SUCCEEDED(load_config()) && ((config >> 5) & 1)) + { static const u16 verPattern[] = u"Ver."; const u32 currentFirm = ((config >> 12) & 1); const u32 currentNand = ((config >> 13) & 3); @@ -217,6 +233,7 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ sizeof(verPattern) - sizeof(u16), 1 ); } + break; } @@ -235,6 +252,7 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ stopCartUpdatesPatch, sizeof(stopCartUpdatesPatch), 2 ); + break; } @@ -255,7 +273,8 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ sizeof(secureinfoSigCheckPatch), 1 ); - if(R_SUCCEEDED(load_secureinfo())){ + if(R_SUCCEEDED(load_secureinfo())) + { static const u16 secureinfoFilenamePattern[] = u"SecureInfo_"; static const u16 secureinfoFilenamePatch[] = u"C"; @@ -268,6 +287,7 @@ u32 patch_code(u64 progid, u8 *code, u32 size){ sizeof(secureinfoFilenamePatch) - sizeof(u16), 2 ); } + break; } } diff --git a/loader/Makefile b/loader/Makefile index ba86e0b..f13bf4a 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -16,7 +16,7 @@ include $(DEVKITARM)/3ds_rules # INCLUDES is a list of directories containing header files # SPECS is the directory containing the important build and link files #--------------------------------------------------------------------------------- -export TARGET := $(shell basename $(CURDIR)) +export TARGET := $(shell basename $(CURDIR)) BUILD := build SOURCES := source source/fatfs source/fatfs/sdmmc diff --git a/loader/source/main.c b/loader/source/main.c index f154920..75f65bd 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -4,9 +4,11 @@ #define PAYLOAD_ADDRESS 0x23F00000 -static u32 loadPayload(const char *path){ +static u32 loadPayload(const char *path) +{ FIL payload; unsigned int br; + if(f_open(&payload, path, FA_READ) == FR_OK) { f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br); @@ -18,7 +20,8 @@ static u32 loadPayload(const char *path){ return 0; } -void main(void){ +void main(void) +{ FATFS fs; f_mount(&fs, "0:", 1); diff --git a/loader/source/start.s b/loader/source/start.s index 4cd3d0a..eaa8c5c 100644 --- a/loader/source/start.s +++ b/loader/source/start.s @@ -12,7 +12,4 @@ _start: mcr p15, 0, r0, c7, c6, 0 @ flush D-cache mcr p15, 0, r0, c7, c10, 4 @ drain write buffer - bl main - -.die: - b .die + b main diff --git a/screeninit/Makefile b/screeninit/Makefile index cb66828..7fa9bf2 100755 --- a/screeninit/Makefile +++ b/screeninit/Makefile @@ -16,7 +16,7 @@ include $(DEVKITARM)/3ds_rules # INCLUDES is a list of directories containing header files # SPECS is the directory containing the important build and link files #--------------------------------------------------------------------------------- -export TARGET := $(shell basename $(CURDIR)) +export TARGET := $(shell basename $(CURDIR)) BUILD := build SOURCES := source diff --git a/screeninit/source/main.c b/screeninit/source/main.c index 552373a..01bce2c 100755 --- a/screeninit/source/main.c +++ b/screeninit/source/main.c @@ -1,6 +1,7 @@ #include "types.h" -void main(void){ +void main(void) +{ vu32 *const arm11 = (u32 *)0x1FFFFFF8; *(vu32 *)0x10141200 = 0x1007F; @@ -96,6 +97,7 @@ void main(void){ //Wait for the entry to be set while(!*arm11); + //Jump to it ((void (*)())*arm11)(); } \ No newline at end of file diff --git a/screeninit/source/start.s b/screeninit/source/start.s index c76ce79..a02aa4c 100644 --- a/screeninit/source/start.s +++ b/screeninit/source/start.s @@ -5,7 +5,4 @@ _start: @ Disable interrupts CPSID aif - bl main - -.die: - b .die + b main diff --git a/source/crypto.c b/source/crypto.c index 8763c98..39e6120 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -239,14 +239,16 @@ static const u8 key2[0x10] = { }; //Get Nand CTR key -static void getNandCTR(u8 *buf, u32 console){ +static void getNandCTR(u8 *buf, u32 console) +{ u8 *addr = (console ? (u8 *)0x080D8BBC : (u8 *)0x080D797C) + 0x0F; for(u8 keyLen = 0x10; keyLen; keyLen--) *(buf++) = *(addr--); } //Read firm0 from NAND and write to buffer -void nandFirm0(u8 *outbuf, u32 size, u32 console){ +void nandFirm0(u8 *outbuf, u32 size, u32 console) +{ u8 CTR[0x10]; getNandCTR(CTR, console); @@ -258,8 +260,8 @@ void nandFirm0(u8 *outbuf, u32 size, u32 console){ } //Decrypts the N3DS arm9bin -void decryptArm9Bin(u8 *arm9Section, u32 mode){ - +void decryptArm9Bin(u8 *arm9Section, u32 mode) +{ //Firm keys u8 keyY[0x10]; u8 CTR[0x10]; @@ -268,12 +270,15 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode){ //Setup keys needed for arm9bin decryption memcpy(keyY, arm9Section + 0x10, 0x10); memcpy(CTR, arm9Section + 0x20, 0x10); + + //Calculate the size of the ARM9 binary u32 size = 0; //http://stackoverflow.com/questions/12791077/atoi-implementation-in-c for(u8 *tmp = arm9Section + 0x30; *tmp; tmp++) size = (size << 3) + (size << 1) + (*tmp) - '0'; - if(mode){ + if(mode) + { u8 keyX[0x10]; //Set 0x11 to key2 for the arm9bin and misc keys @@ -292,15 +297,16 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode){ } //Sets the N3DS 9.6 KeyXs -void setKeyXs(u8 *arm9Section){ - +void setKeyXs(u8 *arm9Section) +{ u8 *keyData = arm9Section + 0x89814; u8 *decKey = keyData + 0x10; //Set keys 0x19..0x1F keyXs aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); aes_use_keyslot(0x11); - for(u8 slot = 0x19; slot < 0x20; slot++){ + for(u8 slot = 0x19; slot < 0x20; slot++) + { aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0); aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); *(keyData + 0xF) += 1; diff --git a/source/draw.c b/source/draw.c index db5ff14..cee5928 100644 --- a/source/draw.c +++ b/source/draw.c @@ -20,38 +20,47 @@ static const struct fb { u8 *bottom; } *const fb = (struct fb *)0x23FFFE00; -static inline int strlen(const char *string){ +static inline int strlen(const char *string) +{ char *stringEnd = (char *)string; while(*stringEnd) stringEnd++; return stringEnd - string; } -void clearScreens(void){ +void clearScreens(void) +{ memset32(fb->top_left, 0, 0x46500); memset32(fb->top_right, 0, 0x46500); memset32(fb->bottom, 0, 0x38400); } -void loadSplash(void){ +void loadSplash(void) +{ clearScreens(); //Don't delay boot if no splash image is on the SD if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) + - fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){ - u64 i = 0x1300000; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func + fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)) + { + u64 i = 0x1300000; + while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func } } -void drawCharacter(char character, int posX, int posY, u32 color){ +void drawCharacter(char character, int posX, int posY, u32 color) +{ u8 *const select = fb->top_left; - for(int y = 0; y < 8; y++){ + for(int y = 0; y < 8; y++) + { char charPos = font[character * 8 + y]; - for(int x = 7; x >= 0; x--){ + for(int x = 7; x >= 0; x--) + { int screenPos = (posX * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - posY - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT; - if ((charPos >> x) & 1) { + if ((charPos >> x) & 1) + { select[screenPos] = color >> 16; select[screenPos + 1] = color >> 8; select[screenPos + 2] = color; @@ -60,15 +69,19 @@ void drawCharacter(char character, int posX, int posY, u32 color){ } } -int drawString(const char *string, int posX, int posY, u32 color){ +int drawString(const char *string, int posX, int posY, u32 color) +{ int length = strlen(string); - for(int i = 0, line_i = 0; i < length; i++, line_i++){ - if(string[i] == '\n'){ + for(int i = 0, line_i = 0; i < length; i++, line_i++) + { + if(string[i] == '\n') + { posY += SPACING_Y; line_i = 0; i++; - } else if(line_i >= (SCREEN_TOP_WIDTH - posX) / SPACING_X){ + } else if(line_i >= (SCREEN_TOP_WIDTH - posX) / SPACING_X) + { // Make sure we never get out of the screen. posY += SPACING_Y; line_i = 2; // Little offset so we know the same string continues. diff --git a/source/emunand.c b/source/emunand.c index 51c1575..93138f2 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -8,7 +8,8 @@ #include "memory.h" #include "fatfs/sdmmc/sdmmc.h" -void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND){ +void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND) +{ u8 *const temp = (u8 *)0x24300000; const u32 nandSize = getMMCDevice(0)->total_size; @@ -16,19 +17,24 @@ void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND){ (nandSize > 0x200000 ? 0x400000 : 0x200000); //Check for RedNAND - if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0){ - if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ + if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0) + { + if(*(u32 *)(temp + 0x100) == NCSD_MAGIC) + { *off = nandOffset + 1; *head = nandOffset + 1; } //Check for Gateway emuNAND - else if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){ - if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){ + else if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0) + { + if(*(u32 *)(temp + 0x100) == NCSD_MAGIC) + { *off = nandOffset; *head = nandOffset + nandSize; } //Fallback to the first emuNAND if there's no second one - else if(*emuNAND == 2){ + else if(*emuNAND == 2) + { *emuNAND = 1; getEmunandSect(off, head, emuNAND); } @@ -37,7 +43,8 @@ void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND){ } } -u32 getSDMMC(u8 *pos, u32 size){ +u32 getSDMMC(u8 *pos, u32 size) +{ //Look for struct code const u8 pattern[] = {0x21, 0x20, 0x18, 0x20}; const u8 *off = memsearch(pos, pattern, size, 4) - 1; @@ -45,7 +52,8 @@ u32 getSDMMC(u8 *pos, u32 size){ return *(u32 *)(off + 0x0A) + *(u32 *)(off + 0x0E); } -void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff){ +void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff) +{ //Look for read/write code const u8 pattern[] = {0x1E, 0x00, 0xC8, 0x05}; @@ -53,14 +61,16 @@ void getEmuRW(u8 *pos, u32 size, u32 *readOff, u32 *writeOff){ *writeOff = (u32)memsearch((u8 *)(*readOff + 0xA), pattern, 0x100, 4) - 6; } -u32 *getMPU(u8 *pos, u32 size){ +u32 *getMPU(u8 *pos, u32 size) +{ //Look for MPU pattern const u8 pattern[] = {0x03, 0x00, 0x24, 0x00}; return (u32 *)memsearch(pos, pattern, size, 4); } -void *getEmuCode(u8 *proc9Offset){ +void *getEmuCode(u8 *proc9Offset) +{ const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; //Looking for the last free space before Process9 diff --git a/source/firm.c b/source/firm.c index dc4cf1c..5a34c72 100755 --- a/source/firm.c +++ b/source/firm.c @@ -38,14 +38,17 @@ static u32 firmSize, emuOffset, emuHeader; -void setupCFW(void){ - +void setupCFW(void) +{ //Determine if booting with A9LH - u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0; + u32 a9lhBoot = !PDN_SPI_CNT ? 1 : 0; + //Retrieve the last booted FIRM u8 previousFirm = CFG_BOOTENV; + //Detect the console being used console = (PDN_MPCORE_CFG == 1) ? 0 : 1; + //Get pressed buttons u16 pressed = HID_PAD; @@ -57,14 +60,18 @@ void setupCFW(void){ //Determine if A9LH is installed and the user has an updated sysNAND u32 updatedSys; - if(a9lhBoot || (config >> 2) & 1){ + if(a9lhBoot || (config >> 2) & 1) + { if(pressed == SAFE_MODE) error("Using Safe Mode would brick you, or remove A9LH!"); a9lhSetup = 1; + //Check setting for > 9.2 sysNAND updatedSys = config & 1; - } else{ + } + else + { a9lhSetup = 0; updatedSys = 0; } @@ -73,29 +80,35 @@ void setupCFW(void){ /* If booting with A9LH, it's a MCU reboot and a previous configuration exists, try to force boot options */ - if(a9lhBoot && previousFirm && needConfig == 1){ + if(a9lhBoot && previousFirm && needConfig == 1) + { //Always force a sysNAND boot when quitting AGB_FIRM - if(previousFirm == 7){ + if(previousFirm == 7) + { mode = updatedSys ? 1 : (config >> 12) & 1; emuNAND = 0; + needConfig = 0; + //Flag to prevent multiple boot options-forcing tempConfig |= 1 << 15; - needConfig = 0; - /* Else, force the last used boot options unless A, L or R are pressed + } + /* Else, force the last used boot options unless A/L/R/SELECT are pressed or the no-forcing flag is set */ - } else if(!(pressed & OPTION_BUTTONS) && !((config >> 15) & 1)){ + else if(!(pressed & OPTION_BUTTONS) && !((config >> 15) & 1)) + { mode = (config >> 12) & 1; emuNAND = (config >> 13) & 3; needConfig = 0; } } - if(needConfig){ - + //Boot options aren't being forced + if(needConfig) + { /* If L and one of the payload buttons are pressed, and if not using A9LH the Safe Mode combo is not pressed, chainload an external payload */ - if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) && - pressed != SAFE_MODE) loadPayload(); + if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) && pressed != SAFE_MODE) + loadPayload(); //If no configuration file exists or SELECT is held, load configuration menu if(needConfig == 2 || (pressed & BUTTON_SELECT)) @@ -104,14 +117,15 @@ void setupCFW(void){ //If screens are inited, load splash screen if(PDN_GPU_CNT != 1) loadSplash(); - /* If L is pressed, boot 9.0 FIRM */ + /* If L is pressed, or L or R are not pressed when it is the default FIRM, + boot 9.0 FIRM */ mode = ((config >> 3) & 1) ? ((!(pressed & BUTTON_L1R1)) ? 0 : 1) : ((pressed & BUTTON_L1) ? 0 : 1); /* 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 */ - if((updatedSys && (!mode || (pressed & BUTTON_R1))) || - (!updatedSys && mode && !(pressed & BUTTON_R1))){ + if((updatedSys && (!mode || (pressed & BUTTON_R1))) || (!updatedSys && mode && !(pressed & BUTTON_R1))) + { //If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND emuNAND = (mode && ((!(pressed & BUTTON_B)) == ((config >> 4) & 1))) ? 2 : 1; } else emuNAND = 0; @@ -124,7 +138,8 @@ void setupCFW(void){ u32 usePatchedFirmSet = ((config >> 1) & 1); - while(1){ + while(1) + { /* Determine which patched FIRM we need to write or attempt to use (if any). Patched 9.0 FIRM is only needed if "Use pre-patched FIRMs" is set */ selectedFirm = mode ? (emuNAND ? (emuNAND == 1 ? 2 : 3) : 1) : @@ -133,11 +148,15 @@ void setupCFW(void){ //If "Use pre-patched FIRMs" is set and the appropriate FIRM exists, use it if(usePatchedFirmSet && fileExists(patchedFirms[selectedFirm - 1])) usePatchedFirm = 1; - //Detect EmuNAND - else if(emuNAND){ + + else if(emuNAND) + { + //Detect EmuNAND getEmunandSect(&emuOffset, &emuHeader, &emuNAND); + //If none exists, force SysNAND + 9.6/10.x FIRM and re-detect patched FIRMs - if(!emuNAND){ + if(!emuNAND) + { mode = 1; continue; } @@ -148,29 +167,34 @@ void setupCFW(void){ tempConfig |= (emuNAND << 13) | (mode << 12); //If the boot configuration is different from previously, overwrite it - if(tempConfig != (config & 0xFFF000)){ + if(tempConfig != (config & 0xFFF000)) + { //Preserve user settings (first 12 bits) tempConfig |= config & 0xFFF; + fileWrite(&tempConfig, configPath, 3); } } //Load FIRM into FCRAM -void loadFirm(void){ - +void loadFirm(void) +{ //If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND - if(!usePatchedFirm && !a9lhSetup && !mode){ + if(!usePatchedFirm && !a9lhSetup && !mode) + { //Read FIRM from NAND and write to FCRAM firmSize = console ? 0xF2000 : 0xE9000; nandFirm0((u8 *)firm, firmSize, console); + //Check for correct decryption if(memcmp(firm, "FIRM", 4) != 0) error("Couldn't decrypt NAND FIRM0 (O3DS not on 9.x?)"); } //Load FIRM from SD - else{ + else + { const char *path = usePatchedFirm ? patchedFirms[selectedFirm - 1] : - (mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin"); + (mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin"); firmSize = fileSize(path); if(!firmSize) error("aurei/firmware(90).bin doesn't exist"); fileRead(firm, path, firmSize); @@ -188,8 +212,8 @@ void loadFirm(void){ } //NAND redirection -static inline void loadEmu(u8 *proc9Offset){ - +static inline void patchEmuNAND(u8 *proc9Offset) +{ //Copy emuNAND code void *emuCodeOffset = getEmuCode(proc9Offset); memcpy(emuCodeOffset, emunand, emunand_size); @@ -227,49 +251,75 @@ static inline void loadEmu(u8 *proc9Offset){ *(mpuOffset + 9) = mpuPatch[2]; } -//Patches -void patchFirm(void){ +static inline void patchReboots(u8 *proc9Offset) +{ + //Calculate offset for the firmlaunch code + void *rebootOffset = getReboot(arm9Section, section[2].size); + //Calculate offset for the fOpen function + u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset); + + //Copy firmlaunch code + memcpy(rebootOffset, reboot, reboot_size); + + //Put the fOpen offset in the right location + u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4); + *pos_fopen = fOpenOffset; + + //Patch path for emuNAND-patched FIRM + if(emuNAND) + { + void *pos_path = memsearch(rebootOffset, L"sy", reboot_size, 4); + memcpy(pos_path, emuNAND == 1 ? L"emu" : L"em2", 5); + } +} + +static inline void injectLoader(void) +{ + u32 loaderOffset, + loaderSize; + + getLoader((u8 *)firm + section[0].offset, section[0].size, &loaderOffset, &loaderSize); + + //Check that the injector CXI isn't larger than the original + if(injector_size <= (int)loaderSize) + { + memset((void *)loaderOffset, 0, loaderSize); + memcpy((void *)loaderOffset, injector, injector_size); + + //Patch content size and ExeFS size to match the repaced loader's ones + *((u32 *)loaderOffset + 0x41) = loaderSize / 0x200; + *((u32 *)loaderOffset + 0x69) = loaderSize / 0x200 - 5; + } +} + +//Patches +void patchFirm(void) +{ //Skip patching if(usePatchedFirm) return; - if(mode || emuNAND){ + if(mode || emuNAND) + { //Find the Process9 NCCH location u8 *proc9Offset = getProc9(arm9Section, section[2].size); //Apply emuNAND patches - if(emuNAND) loadEmu(proc9Offset); + if(emuNAND) patchEmuNAND(proc9Offset); - //Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax - if(mode){ - //Calculate offset for the firmlaunch code - void *rebootOffset = getReboot(arm9Section, section[2].size); - //Calculate offset for the fOpen function - u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset); - - //Copy firmlaunch code - memcpy(rebootOffset, reboot, reboot_size); - - //Put the fOpen offset in the right location - u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4); - *pos_fopen = fOpenOffset; - - //Patch path for emuNAND-patched FIRM - if(emuNAND){ - void *pos_path = memsearch(rebootOffset, L"sy", reboot_size, 4); - memcpy(pos_path, emuNAND == 1 ? L"emu" : L"em2", 5); - } - } + //Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax + if(mode) patchReboots(proc9Offset); } - if(a9lhSetup && !emuNAND){ - //Patch FIRM partitions writes on sysNAND to protect A9LH + //Apply FIRM0/1 writes patches on sysNAND to protect A9LH + if(a9lhSetup && !emuNAND) + { u16 *writeOffset = getFirmWrite(arm9Section, section[2].size); *writeOffset = writeBlock[0]; *(writeOffset + 1) = writeBlock[1]; } - //Disable signature checks + //Apply signature checks patches u32 sigOffset, sigOffset2; @@ -279,18 +329,7 @@ void patchFirm(void){ *((u16 *)sigOffset2 + 1) = sigPatch[1]; //Replace the FIRM loader with the injector - u32 loaderOffset, - loaderSize; - - getLoader((u8 *)firm + section[0].offset, section[0].size, &loaderOffset, &loaderSize); - //Check that the injector CXI isn't larger than the original - if(injector_size <= (int)loaderSize){ - memset((void *)loaderOffset, 0, loaderSize); - memcpy((void *)loaderOffset, injector, injector_size); - //Patch content size and ExeFS size to match the repaced loader's ones - *((u32 *)loaderOffset + 0x41) = loaderSize / 0x200; - *((u32 *)loaderOffset + 0x69) = loaderSize / 0x200 - 5; - } + injectLoader(); //Patch ARM9 entrypoint on N3DS to skip arm9loader if(console) @@ -302,8 +341,8 @@ void patchFirm(void){ error("Couldn't write the patched FIRM (no free space?)"); } -void launchFirm(void){ - +void launchFirm(void) +{ if(console && mode) setKeyXs(arm9Section); //Copy firm partitions to respective memory locations diff --git a/source/fs.c b/source/fs.c index d5fb4a8..15c095f 100644 --- a/source/fs.c +++ b/source/fs.c @@ -9,18 +9,21 @@ static FATFS fs; -u32 mountSD(void){ +u32 mountSD(void) +{ if(f_mount(&fs, "0:", 1) != FR_OK) return 0; return 1; } -u32 fileRead(void *dest, const char *path, u32 size){ +u32 fileRead(void *dest, const char *path, u32 size) +{ FRESULT fr; FIL fp; unsigned int br = 0; fr = f_open(&fp, path, FA_READ); - if(fr == FR_OK){ + if(fr == FR_OK) + { if(!size) size = f_size(&fp); fr = f_read(&fp, dest, size, &br); } @@ -29,7 +32,8 @@ u32 fileRead(void *dest, const char *path, u32 size){ return fr ? 0 : 1; } -u32 fileWrite(const void *buffer, const char *path, u32 size){ +u32 fileWrite(const void *buffer, const char *path, u32 size) +{ FRESULT fr; FIL fp; unsigned int br = 0; @@ -41,7 +45,8 @@ u32 fileWrite(const void *buffer, const char *path, u32 size){ return fr ? 0 : 1; } -u32 fileSize(const char *path){ +u32 fileSize(const char *path) +{ FIL fp; u32 size = 0; @@ -52,7 +57,8 @@ u32 fileSize(const char *path){ return size; } -u32 fileExists(const char *path){ +u32 fileExists(const char *path) +{ FIL fp; u32 exists = 0; @@ -62,6 +68,7 @@ u32 fileExists(const char *path){ return exists; } -void fileDelete(const char *path){ +void fileDelete(const char *path) +{ f_unlink(path); } \ No newline at end of file diff --git a/source/i2c.c b/source/i2c.c index 6f03579..cdbb9a8 100644 --- a/source/i2c.c +++ b/source/i2c.c @@ -10,11 +10,13 @@ static const struct { u8 bus_id, reg_addr; } dev_data[] = { {2, 0xA4}, {2, 0x9A}, {2, 0xA0}, }; -static inline u8 i2cGetDeviceBusId(u8 device_id) { +static inline u8 i2cGetDeviceBusId(u8 device_id) +{ return dev_data[device_id].bus_id; } -static inline u8 i2cGetDeviceRegAddr(u8 device_id) { +static inline u8 i2cGetDeviceRegAddr(u8 device_id) +{ return dev_data[device_id].reg_addr; } @@ -26,7 +28,8 @@ static vu8* reg_data_addrs[] = { (vu8*)(I2C3_REG_OFF + I2C_REG_DATA), }; -static inline vu8* i2cGetDataReg(u8 bus_id) { +static inline vu8* i2cGetDataReg(u8 bus_id) +{ return reg_data_addrs[bus_id]; } @@ -38,22 +41,27 @@ static vu8* reg_cnt_addrs[] = { (vu8*)(I2C3_REG_OFF + I2C_REG_CNT), }; -static inline vu8* i2cGetCntReg(u8 bus_id) { +static inline vu8* i2cGetCntReg(u8 bus_id) +{ return reg_cnt_addrs[bus_id]; } //----------------------------------------------------------------------------- -static inline void i2cWaitBusy(u8 bus_id) { +static inline void i2cWaitBusy(u8 bus_id) +{ while (*i2cGetCntReg(bus_id) & 0x80); } -static inline u32 i2cGetResult(u8 bus_id) { +static inline u32 i2cGetResult(u8 bus_id) +{ i2cWaitBusy(bus_id); + return (*i2cGetCntReg(bus_id) >> 4) & 1; } -static void i2cStop(u8 bus_id, u8 arg0) { +static void i2cStop(u8 bus_id, u8 arg0) +{ *i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0; i2cWaitBusy(bus_id); *i2cGetCntReg(bus_id) = 0xC5; @@ -61,32 +69,40 @@ static void i2cStop(u8 bus_id, u8 arg0) { //----------------------------------------------------------------------------- -static u32 i2cSelectDevice(u8 bus_id, u8 dev_reg) { +static u32 i2cSelectDevice(u8 bus_id, u8 dev_reg) +{ i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = dev_reg; *i2cGetCntReg(bus_id) = 0xC2; + return i2cGetResult(bus_id); } -static u32 i2cSelectRegister(u8 bus_id, u8 reg) { +static u32 i2cSelectRegister(u8 bus_id, u8 reg) +{ i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = reg; *i2cGetCntReg(bus_id) = 0xC0; + return i2cGetResult(bus_id); } //----------------------------------------------------------------------------- -u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) { +u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) +{ u8 bus_id = i2cGetDeviceBusId(dev_id); u8 dev_addr = i2cGetDeviceRegAddr(dev_id); - for (int i = 0; i < 8; i++) { - if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) { + for (u32 i = 0; i < 8; i++) + { + if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) + { i2cWaitBusy(bus_id); *i2cGetDataReg(bus_id) = data; *i2cGetCntReg(bus_id) = 0xC1; i2cStop(bus_id, 0); + if (i2cGetResult(bus_id)) return 1; } @@ -95,4 +111,4 @@ u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) { } return 0; -} +} \ No newline at end of file diff --git a/source/loader.c b/source/loader.c index 845e1f9..db33c8c 100644 --- a/source/loader.c +++ b/source/loader.c @@ -12,8 +12,10 @@ #define PAYLOAD_ADDRESS 0x24F00000 -void loadPayload(void){ - if(fileExists("aurei/payloads/default.bin")){ +void loadPayload(void) +{ + if(fileExists("aurei/payloads/default.bin")) + { initScreens(); memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size); ((void (*)())PAYLOAD_ADDRESS)(); diff --git a/source/main.c b/source/main.c index 9d785ea..0ea5977 100644 --- a/source/main.c +++ b/source/main.c @@ -9,7 +9,8 @@ #include "fs.h" #include "firm.h" -void main(void){ +void main(void) +{ mountSD(); setupCFW(); loadFirm(); diff --git a/source/memory.c b/source/memory.c index 05d4cdc..b409d2d 100644 --- a/source/memory.c +++ b/source/memory.c @@ -8,36 +8,43 @@ #include "memory.h" -void memcpy(void *dest, const void *src, u32 size){ +void memcpy(void *dest, const void *src, u32 size) +{ u8 *destc = (u8 *)dest; const u8 *srcc = (const u8 *)src; for(u32 i = 0; i < size; i++) destc[i] = srcc[i]; } -void memset(void *dest, int filler, u32 size){ +void memset(void *dest, int filler, u32 size) +{ u8 *destc = (u8 *)dest; for(u32 i = 0; i < size; i++) destc[i] = (u8)filler; } -void memset32(void *dest, u32 filler, u32 size){ +void memset32(void *dest, u32 filler, u32 size) +{ u32 *dest32 = (u32 *)dest; for (u32 i = 0; i < size / 4; i++) dest32[i] = filler; } -int memcmp(const void *buf1, const void *buf2, u32 size){ +int memcmp(const void *buf1, const void *buf2, u32 size) +{ const u8 *buf1c = (const u8 *)buf1; const u8 *buf2c = (const u8 *)buf2; - for(u32 i = 0; i < size; i++){ + for(u32 i = 0; i < size; i++) + { int cmp = buf1c[i] - buf2c[i]; if(cmp) return cmp; } + return 0; } -u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize){ +u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize) +{ const u8 *patternc = (const u8 *)pattern; //Preprocessing @@ -51,7 +58,8 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize){ //Searching u32 j = 0; - while(j <= size - patternSize){ + while(j <= size - patternSize) + { if(memcmp(patternc, startPos + j, patternSize) == 0) return startPos + j; j += table[startPos[j + patternSize]]; diff --git a/source/patches.c b/source/patches.c index aef053b..b072cd4 100644 --- a/source/patches.c +++ b/source/patches.c @@ -23,11 +23,13 @@ const u16 writeBlock[2] = {0x2000, 0x46C0}; * Functions **************************************************/ -u8 *getProc9(u8 *pos, u32 size){ +u8 *getProc9(u8 *pos, u32 size) +{ return memsearch(pos, "ess9", size, 4); } -void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2){ +void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2) +{ //Look for signature checks const u8 pattern[] = {0xC0, 0x1C, 0x76, 0xE7}, pattern2[] = {0xB5, 0x22, 0x4D, 0x0C}; @@ -36,16 +38,19 @@ void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2){ *off2 = (u32)memsearch(pos, pattern2, size, 4) - 1; } -void *getReboot(u8 *pos, u32 size){ +void *getReboot(u8 *pos, u32 size) +{ //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){ +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; @@ -53,7 +58,8 @@ u32 getfOpen(u8 *proc9Offset, void *rebootOffset){ return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr; } -u16 *getFirmWrite(u8 *pos, u32 size){ +u16 *getFirmWrite(u8 *pos, u32 size) +{ //Look for FIRM writing code u8 *const off = memsearch(pos, "exe:", size, 4); const u8 pattern[] = {0x00, 0x28, 0x01, 0xDA}; @@ -61,7 +67,8 @@ u16 *getFirmWrite(u8 *pos, u32 size){ return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4); } -void getLoader(u8 *pos, u32 size, u32 *loaderOffset, u32 *loaderSize){ +void getLoader(u8 *pos, u32 size, u32 *loaderOffset, u32 *loaderSize) +{ u8 *const off = memsearch(pos, "loade", size, 5); *loaderOffset = (u32)off - 0x200; diff --git a/source/screeninit.c b/source/screeninit.c index 400fe73..81143f2 100644 --- a/source/screeninit.c +++ b/source/screeninit.c @@ -17,8 +17,10 @@ static vu32 *const arm11 = (u32 *)0x1FFFFFF8; -void deinitScreens(void){ - void __attribute__((naked)) ARM11(void){ +void deinitScreens(void) +{ + void __attribute__((naked)) ARM11(void) + { //Disable interrupts __asm(".word 0xF10C01C0"); @@ -32,22 +34,28 @@ void deinitScreens(void){ //Wait for the entry to be set while(!*arm11); + //Jump to it ((void (*)())*arm11)(); } - if(PDN_GPU_CNT != 1){ + if(PDN_GPU_CNT != 1) + { *arm11 = (u32)ARM11; while(*arm11); } } -void initScreens(void){ - memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size); +void initScreens(void) +{ + if(PDN_GPU_CNT == 1) + { + memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size); - if(PDN_GPU_CNT == 1){ *arm11 = SCREENINIT_ADDRESS; while(*arm11); + + //Turn on backlight i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); } diff --git a/source/start.s b/source/start.s index 729f02c..2061b5f 100644 --- a/source/start.s +++ b/source/start.s @@ -50,7 +50,4 @@ _start: mov r1, #0x340 str r1, [r0] - bl main - -.die: - b .die + b main diff --git a/source/utils.c b/source/utils.c index fccf783..b3eafd3 100644 --- a/source/utils.c +++ b/source/utils.c @@ -21,7 +21,8 @@ struct option { u32 enabled; }; -static u16 waitInput(void){ +static u16 waitInput(void) +{ u32 pressedKey = 0; u16 key; @@ -34,7 +35,8 @@ static u16 waitInput(void){ key = HID_PAD; //Make sure it's pressed - for(u32 i = 0x13000; i; i--){ + for(u32 i = 0x13000; i; i--) + { if(key != HID_PAD) break; if(i == 1) pressedKey = 1; } @@ -43,7 +45,8 @@ static u16 waitInput(void){ return key; } -void configureCFW(const char *configPath, const char *firm90Path){ +void configureCFW(const char *configPath, const char *firm90Path) +{ initScreens(); drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE); @@ -62,6 +65,7 @@ void configureCFW(const char *configPath, const char *firm90Path){ //Read and parse the existing configuration u32 tempConfig = 0; fileRead(&tempConfig, configPath, 3); + for(u32 i = 0; i < optionsAmount; i++) options[i].enabled = (tempConfig >> i) & 1; @@ -69,18 +73,22 @@ void configureCFW(const char *configPath, const char *firm90Path){ u32 selectedOption = 0; //Boring configuration menu - while(1){ + while(1) + { u16 pressed = 0; - do{ - for(u32 i = 0; i < optionsAmount; i++){ + do { + for(u32 i = 0; i < optionsAmount; i++) + { options[i].posY = drawString(optionsText[i], 10, !i ? 60 : options[i - 1].posY + SPACING_Y, selectedOption == i ? COLOR_RED : COLOR_WHITE); drawCharacter('x', 10 + SPACING_X, options[i].posY, options[i].enabled ? (selectedOption == i ? COLOR_RED : COLOR_WHITE) : COLOR_BLACK); } + pressed = waitInput(); } while(!(pressed & MENU_BUTTONS)); - switch(pressed){ + switch(pressed) + { case BUTTON_UP: selectedOption = !selectedOption ? optionsAmount - 1 : selectedOption - 1; break; @@ -110,6 +118,7 @@ void configureCFW(const char *configPath, const char *firm90Path){ //Parse and write the selected options for(u32 i = 0; i < optionsAmount; i++) tempConfig |= options[i].enabled << i; + fileWrite(&tempConfig, configPath, 3); //Zero the last booted FIRM flag @@ -120,14 +129,17 @@ void configureCFW(const char *configPath, const char *firm90Path){ while(1); } -void deleteFirms(const char *firmPaths[], u32 firms){ - while(firms){ +void deleteFirms(const char *firmPaths[], u32 firms) +{ + while(firms) + { fileDelete(firmPaths[firms - 1]); firms--; } } -void error(const char *message){ +void error(const char *message) +{ initScreens(); drawString("An error has occurred:", 10, 10, COLOR_RED);