From aa7c2c00097f3eb9cd020e8bdc827c825a1336d5 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 03:51:48 +0200 Subject: [PATCH 1/7] Various changes/cleanups, removed useless code, simplified chronometer functions --- source/crypto.c | 19 +++++++------------ source/firm.c | 36 ++++++++---------------------------- source/fs.c | 4 ++-- source/fs.h | 2 +- source/patches.c | 2 +- source/pin.c | 35 +++++++++++++++-------------------- source/screen.c | 8 ++------ source/screen.h | 2 +- source/utils.c | 18 +++++++++--------- source/utils.h | 2 -- 10 files changed, 46 insertions(+), 82 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index 99ecbff..7014027 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -311,11 +311,8 @@ void ctrNandInit(void) if(isN3DS) { - if(!isDevUnit) - { - u8 __attribute__((aligned(4))) keyY0x5[0x10] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE}; - aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - } + u8 __attribute__((aligned(4))) keyY0x5[0x10] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE}; + aes_setkey(0x05, keyY0x5, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); nandSlot = 0x05; fatStart = 0x5CAD7; @@ -361,11 +358,10 @@ void setRSAMod0DerivedKeys(void) aes_setkey(0x25, keyX0x25, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(0x2F, keyY0x2F, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - + /* [3dbrew] The first 0x10-bytes are checked by the v6.0/v7.0 NATIVE_FIRM keyinit function, when non-zero it clears this block and continues to do the key generation. - Otherwise when this block was already all-zero, it immediately returns. - */ + Otherwise when this block was already all-zero, it immediately returns. */ memset32((void *)0x01FFCD00, 0, 0x10); } } @@ -408,7 +404,7 @@ void arm9Loader(u8 *arm9Section) //Firm keys u8 __attribute__((aligned(4))) keyY[0x10]; - u8 __attribute__((aligned(4))) arm9BinCTR[0x10]; + u8 __attribute__((aligned(4))) arm9BinCTR[0x10]; u8 arm9BinSlot = a9lVersion ? 0x16 : 0x15; //Setup keys needed for arm9bin decryption @@ -424,7 +420,7 @@ void arm9Loader(u8 *arm9Section) if(a9lVersion) { u8 __attribute__((aligned(4))) keyX[0x10]; - + if(!isDevUnit) { const u8 __attribute__((aligned(4))) key1[0x10] = {0x07, 0x29, 0x44, 0x38, 0xF8, 0xC9, 0x75, 0x93, 0xAA, 0x0E, 0x4A, 0xB4, 0xAE, 0x84, 0xC1, 0xD8}; @@ -453,11 +449,10 @@ void arm9Loader(u8 *arm9Section) //Set keys 0x19..0x1F keyXs aes_use_keyslot(0x11); - for(u8 slot = 0x19; slot < 0x20; slot++) + for(u8 slot = 0x19; slot < 0x20; slot++, keyData[0xF]++) { 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/firm.c b/source/firm.c index 0cd33e7..71043aa 100755 --- a/source/firm.c +++ b/source/firm.c @@ -56,8 +56,7 @@ void main(void) isA9lh; u32 newConfig, - emuHeader, - nbChronoStarted = 0; + emuHeader; FirmwareType firmType; FirmwareSource nandType; @@ -135,12 +134,12 @@ void main(void) if(needConfig != DONT_CONFIGURE) { //If no configuration file exists or SELECT is held, load configuration menu - bool shouldLoadConfigurationMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); - bool pinExists = CONFIG(7) && readPin(&pin); + bool shouldLoadConfigurationMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)), + pinExists = CONFIG(7) && readPin(&pin); if(pinExists || shouldLoadConfigurationMenu) { - bool needToDeinit = initScreens(); + initScreens(); //If we get here we should check the PIN (if it exists) in all cases if(pinExists) verifyPin(&pin, true); @@ -154,21 +153,11 @@ void main(void) //Zero the last booted FIRM flag CFG_BOOTENV = 0; - nbChronoStarted = 1; - chrono(0); chrono(2); //Update pressed buttons pressed = HID_PAD; } - - if(needToDeinit) - { - //Turn off backlight - i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x16); - deinitScreens(); - PDN_GPU_CNT = 1; - } } if(isA9lh && !CFG_BOOTENV && pressed == SAFE_MODE) @@ -183,22 +172,19 @@ void main(void) if(CONFIG(6) && loadSplash()) { - nbChronoStarted = 2; - chrono(0); chrono(3); - nbChronoStarted = 0; + + //Update pressed buttons pressed = HID_PAD; } bool shouldLoadPayload = (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)); - if(shouldLoadPayload) - loadPayload(pressed, nbChronoStarted != 2); + if(shouldLoadPayload) loadPayload(pressed); if(!CONFIG(6) && loadSplash()) { - nbChronoStarted = 2; - chrono(0); + chrono(3); } //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one @@ -266,12 +252,6 @@ void main(void) break; } - if(nbChronoStarted) - { - if(nbChronoStarted == 2) chrono(3); - stopChrono(); - } - launchFirm(firmType, isFirmlaunch); } diff --git a/source/fs.c b/source/fs.c index 0358b87..59d1c0d 100644 --- a/source/fs.c +++ b/source/fs.c @@ -81,7 +81,7 @@ void createDirectory(const char *path) f_mkdir(path); } -void loadPayload(u32 pressed, bool needToInitScreens) +void loadPayload(u32 pressed) { const char *pattern; @@ -106,7 +106,7 @@ void loadPayload(u32 pressed, bool needToInitScreens) if(result == FR_OK && info.fname[0]) { - if(needToInitScreens) initScreens(); + initScreens(); u32 *const loaderAddress = (u32 *)0x24FFFF00; diff --git a/source/fs.h b/source/fs.h index 4e1456d..805c099 100644 --- a/source/fs.h +++ b/source/fs.h @@ -33,5 +33,5 @@ u32 fileRead(void *dest, const char *path); u32 getFileSize(const char *path); bool fileWrite(const void *buffer, const char *path, u32 size); void createDirectory(const char *path); -void loadPayload(u32 pressed, bool needToInitScreens); +void loadPayload(u32 pressed); u32 firmRead(void *dest, u32 firmType); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index f95a739..a9cb7b6 100644 --- a/source/patches.c +++ b/source/patches.c @@ -185,7 +185,7 @@ u32 getLoader(u8 *pos, u32 *loaderSize) u8 *off = pos; u32 size; - while(1) + while(true) { size = *(u32 *)(off + 0x104) * 0x200; if(*(u32 *)(off + 0x200) == 0x64616F6C) break; diff --git a/source/pin.c b/source/pin.c index 7920708..772afa4 100644 --- a/source/pin.c +++ b/source/pin.c @@ -39,9 +39,10 @@ bool readPin(PINData *out) { u8 __attribute__((aligned(4))) zeroes[16] = {0}; u8 __attribute__((aligned(4))) tmp[32] = {0}; + if(fileRead(out, "/luma/pin.bin") != sizeof(PINData)) return false; - else if(memcmp(out->magic, "PINF", 4) != 0) return false; - + if(memcmp(out->magic, "PINF", 4) != 0) return false; + computePINHash(tmp, zeroes, 1); return memcmp(out->testHash, tmp, 32) == 0; //test vector verification (SD card has (or hasn't) been used on another console) } @@ -62,16 +63,15 @@ PINData newPin(void) drawString("Enter your NEW PIN: ", 10, 10, COLOR_WHITE); - u32 pressed = 0; - // Set the default value as 0x00 so we can check if there are any unentered characters. u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; // pad to AES block length + u32 cnt = 0; int charDrawPos = 20 * SPACING_X; - int cnt = 0; - + while(true) { + u32 pressed; do { pressed = waitInput(); @@ -89,9 +89,8 @@ PINData newPin(void) charDrawPos += 2 * SPACING_X; // we leave the rest of the array zeroed out. - if (cnt >= PIN_LENGTH) + if(cnt >= PIN_LENGTH) { - PINData pin = {0}; u8 __attribute__((aligned(4))) tmp[32] = {0}; u8 __attribute__((aligned(4))) zeroes[16] = {0}; @@ -119,16 +118,16 @@ void verifyPin(PINData *in, bool allowQuit) drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - u32 pressed = 0; - // Set the default characters as 0x00 so we can check if there are any unentered characters. u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; + u32 cnt = 0; bool unlock; - int charDrawPos = 5 * SPACING_X, cnt = 0; + int charDrawPos = 5 * SPACING_X; while(true) { + u32 pressed; do { pressed = waitInput(); @@ -159,22 +158,18 @@ void verifyPin(PINData *in, bool allowQuit) computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); unlock = memcmp(in->hash, tmp, 32) == 0; - if (!unlock) - { - // re zero out all 16 just in case. - memset32(enteredPassword, 0, 16); - - pressed = 0; + if(!unlock) + { charDrawPos = 5 * SPACING_X; cnt = 0; - + clearScreens(); - + drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); drawString("Wrong pin! Try again!", 10, 10 + 3 * SPACING_Y, COLOR_RED); } - else return; + else break; } } } \ No newline at end of file diff --git a/source/screen.c b/source/screen.c index b56a1e5..e94844d 100644 --- a/source/screen.c +++ b/source/screen.c @@ -140,10 +140,8 @@ void clearScreens(void) invokeArm11Function(ARM11); } -bool initScreens(void) +void initScreens(void) { - bool needToInit = PDN_GPU_CNT == 1; - void __attribute__((naked)) ARM11(void) { //Disable interrupts @@ -242,7 +240,7 @@ bool initScreens(void) WAIT_FOR_ARM9(); } - if(needToInit) + if(PDN_GPU_CNT == 1) { flushDCacheRange(&config, 4); flushDCacheRange((void *)fb, sizeof(struct fb)); @@ -254,6 +252,4 @@ bool initScreens(void) else updateBrightness(MULTICONFIG(0)); clearScreens(); - - return needToInit; } \ No newline at end of file diff --git a/source/screen.h b/source/screen.h index e387825..a7af345 100644 --- a/source/screen.h +++ b/source/screen.h @@ -42,4 +42,4 @@ static volatile struct fb { void deinitScreens(void); void updateBrightness(u32 brightnessIndex); void clearScreens(void); -bool initScreens(void); \ No newline at end of file +void initScreens(void); \ No newline at end of file diff --git a/source/utils.c b/source/utils.c index f180ecd..5dd4a6c 100644 --- a/source/utils.c +++ b/source/utils.c @@ -84,14 +84,19 @@ static inline void startChrono(u64 initialTicks) for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; enabled } +static inline void stopChrono(void) +{ + for(u32 i = 0; i < 4; i++) REG_TIMER_CNT(i) &= ~0x80; +} + void chrono(u32 seconds) { - static u64 startingTicks = 0; + startChrono(0); - if(!startingTicks) startChrono(0); + u64 startingTicks = 0; + for(u32 i = 0; i < 4; i++) startingTicks |= REG_TIMER_VAL(i) << (16 * i); u64 res; - do { res = 0; @@ -99,12 +104,7 @@ void chrono(u32 seconds) } while(res - startingTicks < seconds * TICKS_PER_SEC); - if(!seconds) startingTicks = res; -} - -void stopChrono(void) -{ - for(u32 i = 0; i < 4; i++) REG_TIMER_CNT(i) &= ~0x80; + stopChrono(); } void error(const char *message) diff --git a/source/utils.h b/source/utils.h index 80deb90..bf74e1c 100644 --- a/source/utils.h +++ b/source/utils.h @@ -31,7 +31,5 @@ u32 waitInput(void); void mcuReboot(void); void mcuPowerOff(void); - void chrono(u32 seconds); -void stopChrono(void); void error(const char *message); \ No newline at end of file From c9c373f6078466085c185ba4f5fd908ae02a7999 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 13:11:27 +0200 Subject: [PATCH 2/7] Move stuff from firm.c --- source/config.c | 2 ++ source/draw.c | 2 ++ source/firm.c | 18 ++---------------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/source/config.c b/source/config.c index a16bdf7..6949b7e 100644 --- a/source/config.c +++ b/source/config.c @@ -201,4 +201,6 @@ void configureCFW(const char *configPath) //Wait for the pressed buttons to change while(HID_PAD == BUTTON_START); + + chrono(2); } \ No newline at end of file diff --git a/source/draw.c b/source/draw.c index 2dfbea3..b23bc09 100644 --- a/source/draw.c +++ b/source/draw.c @@ -51,6 +51,8 @@ bool loadSplash(void) fileRead(fb->top_left, "/luma/splash.bin"); fileRead(fb->bottom, "/luma/splashbottom.bin"); + chrono(3); + return true; } diff --git a/source/firm.c b/source/firm.c index 71043aa..fa619f3 100755 --- a/source/firm.c +++ b/source/firm.c @@ -150,11 +150,6 @@ void main(void) if(!pinExists && CONFIG(7)) pin = newPin(); - //Zero the last booted FIRM flag - CFG_BOOTENV = 0; - - chrono(2); - //Update pressed buttons pressed = HID_PAD; } @@ -169,23 +164,14 @@ void main(void) { /* If L and R/A/Select or one of the single payload buttons are pressed, chainload an external payload (the PIN, if any, has been verified)*/ - - if(CONFIG(6) && loadSplash()) - { - chrono(3); - //Update pressed buttons - pressed = HID_PAD; - } + if(CONFIG(6) && loadSplash()) pressed = HID_PAD; bool shouldLoadPayload = (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)); if(shouldLoadPayload) loadPayload(pressed); - if(!CONFIG(6) && loadSplash()) - { - chrono(3); - } + if(!CONFIG(6)) loadSplash(); //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one if(pressed & BUTTON_R1) From 83a849126a92cfb31f02779fb164397ccf3beebc Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 13:23:27 +0200 Subject: [PATCH 3/7] Move stuff from firm.c (2) --- source/config.c | 3 ++- source/firm.c | 26 +++++++++++--------------- source/pin.c | 2 +- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/source/config.c b/source/config.c index 6949b7e..f544a84 100644 --- a/source/config.c +++ b/source/config.c @@ -29,7 +29,8 @@ void configureCFW(const char *configPath) { - clearScreens(); + initScreens(); + drawString(CONFIG_TITLE, 10, 10, COLOR_TITLE); drawString("Press A to select, START to save", 10, 30, COLOR_WHITE); diff --git a/source/firm.c b/source/firm.c index fa619f3..f13de09 100755 --- a/source/firm.c +++ b/source/firm.c @@ -133,26 +133,22 @@ void main(void) //Boot options aren't being forced if(needConfig != DONT_CONFIGURE) { + bool pinExists = CONFIG(7) && readPin(&pin); + + //If we get here we should check the PIN (if it exists) in all cases + if(pinExists) verifyPin(&pin, true); + //If no configuration file exists or SELECT is held, load configuration menu - bool shouldLoadConfigurationMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)), - pinExists = CONFIG(7) && readPin(&pin); + bool shouldLoadConfigurationMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); - if(pinExists || shouldLoadConfigurationMenu) + if(shouldLoadConfigurationMenu) { - initScreens(); + configureCFW(configPath); - //If we get here we should check the PIN (if it exists) in all cases - if(pinExists) verifyPin(&pin, true); + if(!pinExists && CONFIG(7)) pin = newPin(); - if(shouldLoadConfigurationMenu) - { - configureCFW(configPath); - - if(!pinExists && CONFIG(7)) pin = newPin(); - - //Update pressed buttons - pressed = HID_PAD; - } + //Update pressed buttons + pressed = HID_PAD; } if(isA9lh && !CFG_BOOTENV && pressed == SAFE_MODE) diff --git a/source/pin.c b/source/pin.c index 772afa4..d228a4f 100644 --- a/source/pin.c +++ b/source/pin.c @@ -113,7 +113,7 @@ PINData newPin(void) void verifyPin(PINData *in, bool allowQuit) { - clearScreens(); + initScreens(); drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); From 7ab59e420a5c93b62007ef88523a3ce0afb0b30f Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 13:28:43 +0200 Subject: [PATCH 4/7] Fix comment --- source/firm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/firm.c b/source/firm.c index f13de09..ccdedcf 100755 --- a/source/firm.c +++ b/source/firm.c @@ -157,12 +157,11 @@ void main(void) firmSource = FIRMWARE_SYSNAND; } else - { - /* If L and R/A/Select or one of the single payload buttons are pressed, - chainload an external payload (the PIN, if any, has been verified)*/ - + { if(CONFIG(6) && loadSplash()) pressed = HID_PAD; + /* If L and R/A/Select or one of the single payload buttons are pressed, + chainload an external payload (the PIN, if any, has been verified)*/ bool shouldLoadPayload = (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)); if(shouldLoadPayload) loadPayload(pressed); From 5248b96f8a4dbe0107b961ee21634c34422cfb0a Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 13:37:23 +0200 Subject: [PATCH 5/7] No need for this --- source/pin.c | 6 +----- source/utils.c | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/source/pin.c b/source/pin.c index d228a4f..84985ba 100644 --- a/source/pin.c +++ b/source/pin.c @@ -138,11 +138,7 @@ void verifyPin(PINData *in, bool allowQuit) if(!allowQuit) pressed &= ~BUTTON_START; if(!pressed) continue; - if(pressed & BUTTON_START) - { - clearScreens(); - mcuPowerOff(); - } + if(pressed & BUTTON_START) mcuPowerOff(); char key = PINKeyToLetter(pressed); enteredPassword[cnt++] = (u8)key; // add character to password. diff --git a/source/utils.c b/source/utils.c index 5dd4a6c..3146bea 100644 --- a/source/utils.c +++ b/source/utils.c @@ -110,7 +110,6 @@ void chrono(u32 seconds) void error(const char *message) { initScreens(); - clearScreens(); drawString("An error has occurred:", 10, 10, COLOR_RED); int posY = drawString(message, 10, 30, COLOR_WHITE); From c1016530772ff8fb6494d180887e31e9c7c1f2fd Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 14:46:33 +0200 Subject: [PATCH 6/7] Clear screens before a power off/reboot --- source/utils.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/utils.c b/source/utils.c index 3146bea..a7d3989 100644 --- a/source/utils.c +++ b/source/utils.c @@ -56,6 +56,8 @@ u32 waitInput(void) void mcuReboot(void) { + if(PDN_GPU_CNT != 1) clearScreens(); + flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); @@ -64,6 +66,8 @@ void mcuReboot(void) void mcuPowerOff(void) { + if(PDN_GPU_CNT != 1) clearScreens(); + flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); From bb117d3d74d946a72f8b9cf07ffa7519a983f12c Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 15 Aug 2016 15:25:44 +0200 Subject: [PATCH 7/7] Clear screens before turning on the backlight to mitigate previous FB contents persisting --- source/screen.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/screen.c b/source/screen.c index e94844d..6b121a6 100644 --- a/source/screen.c +++ b/source/screen.c @@ -246,10 +246,14 @@ void initScreens(void) flushDCacheRange((void *)fb, sizeof(struct fb)); invokeArm11Function(ARM11); + clearScreens(); + //Turn on backlight i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); } - else updateBrightness(MULTICONFIG(0)); - - clearScreens(); + else + { + clearScreens(); + updateBrightness(MULTICONFIG(0)); + } } \ No newline at end of file