diff --git a/include/arm9/firm.h b/include/arm9/firm.h index 0280d0c..db88362 100644 --- a/include/arm9/firm.h +++ b/include/arm9/firm.h @@ -3,12 +3,7 @@ #include "types.h" #include "mem_map.h" -#define FIRM_LOAD_ADDR (VRAM_BASE + 0x200000) -#define FIRM_MAX_SIZE (0x00400000) - -#define FIRM_SECTION_CORRUPTED 0xBAD5EC -#define FIRM_FATAL_ERROR 0xBADBAD -#define FIRM_GOOD 0x900D +#define FIRM_MAX_SIZE (0x00400000) typedef struct { @@ -44,5 +39,5 @@ */ -bool firm_verify(u32 firmSize); +bool firm_verify(u32 fwSize, bool skipHashCheck, bool printInfo); noreturn void firm_launch(void); diff --git a/include/mem_map.h b/include/mem_map.h index 9d43afd..66fd392 100644 --- a/include/mem_map.h +++ b/include/mem_map.h @@ -101,6 +101,7 @@ #define A9_STACK_END (DTCM_BASE + DTCM_SIZE) #define A9_EXC_STACK_START (ITCM_KERNEL_MIRROR + (ITCM_SIZE / 2)) #define A9_EXC_STACK_END (ITCM_KERNEL_MIRROR + ITCM_SIZE) +#define FIRM_LOAD_ADDR (VRAM_BASE + 0x200000) #endif diff --git a/source/arm11/main.c b/source/arm11/main.c index 3f503de..8787374 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -57,7 +57,9 @@ } } + /* Update state, check for changes */ + u8 hidstate = i2cmcu_readreg_hid(); if(hidstate & MCU_HID_POWER_BUTTON_PRESSED) @@ -85,11 +87,5 @@ start_firmlaunch: -/* - // Turn off LCDs and backlight before FIRM launch. - i2cmcu_lcd_poweroff(); - i2cmcu_lcd_backlight_poweroff(); -*/ - return 0; } diff --git a/source/arm9/firm.c b/source/arm9/firm.c index b687159..1b23e20 100644 --- a/source/arm9/firm.c +++ b/source/arm9/firm.c @@ -8,8 +8,9 @@ #undef ARM11 #include "arm9/firm.h" #include "arm9/crypto.h" -#include "cache.h" #include "arm9/ndma.h" +#include "cache.h" +#include "util.h" #include "pxi.h" @@ -111,7 +112,7 @@ __asm__ __volatile__("mov lr, %0\n\tbx %1" : : "r" (ret), "r" (entry9) : "lr", "pc"); } -bool firm_verify(u32 fwSize) +bool firm_verify(u32 fwSize, bool skipHashCheck, bool printInfo) { firm_header *firm_hdr = (firm_header*)FIRM_LOAD_ADDR; const char *res[2] = {"\x1B[31mBAD", "\x1B[32mGOOD"}; @@ -119,12 +120,21 @@ bool retval = true; u32 hash[8]; - if(firm_hdr->magic != 0x4D524946u) + if(fwSize > FIRM_MAX_SIZE) + return false; + + if(fwSize <= sizeof(firm_header)) return false; - printf("ARM9 entry: 0x%"PRIX32"\n", firm_hdr->entrypointarm9); - printf("ARM11 entry: 0x%"PRIX32"\n", firm_hdr->entrypointarm11); - + if(memcmp(firm_hdr->magic, 'FIRM', 4) != 0) + return false; + + if(printInfo) + { + printf("ARM9 entry: 0x%"PRIX32"\n", firm_hdr->entrypointarm9); + printf("ARM11 entry: 0x%"PRIX32"\n", firm_hdr->entrypointarm11); + } + for(u32 i=0; i<4; i++) { firm_sectionheader *section = &firm_hdr->section[i]; @@ -132,23 +142,26 @@ if(section->size == 0) continue; - printf("Section %i:\noffset: 0x%"PRIX32", addr: 0x%"PRIX32", size: 0x%"PRIX32"\n", + if(printInfo) + printf("Section %i:\noffset: 0x%"PRIX32", addr: 0x%"PRIX32", size: 0x%"PRIX32"\n", (int) i, section->offset, section->address, section->size); if(section->offset >= fwSize) { - printf("\x1B[31mBad section offset!\e[0m\n"); + if(printInfo) + printf("\x1B[31mBad section offset!\e[0m\n"); return false; } - if((section->size >> 31) || (section->size + section->offset > fwSize)) + if((section->size >= fwSize) || (section->size + section->offset > fwSize)) { - printf("\x1B[31mBad section size!\e[0m\n"); + if(printInfo) + printf("\x1B[31mBad section size!\e[0m\n"); return false; } // check for bad sections - const u32 numEntries = sizeof(firmProtectedAreas)/sizeof(firmProtectedArea); + const u32 numEntries = arrayEntries(firmProtectedArea); for(u32 j=0; joffset), section->size, hash, - SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); - isValid = memcmp(hash, section->hash, 32) == 0; - printf("Hash: %s\e[0m\n", res[isValid]); - - retval &= isValid; + + if(!skipHashCheck) + { + sha((u32*)(FIRM_LOAD_ADDR + section->offset), section->size, hash, + SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); + isValid = memcmp(hash, section->hash, 32) == 0; + + if(printInfo) + printf("Hash: %s\e[0m\n", res[isValid]); + + retval &= isValid; + } } return retval; diff --git a/source/arm9/menu_firmloader.c b/source/arm9/menu_firmloader.c index 6649746..3954966 100644 --- a/source/arm9/menu_firmloader.c +++ b/source/arm9/menu_firmloader.c @@ -17,7 +17,7 @@ static int firmLoaded = 0; -static bool tryLoadFirmware(const char *filepath); +static bool tryLoadFirmware(const char *filepath, bool skipHashCheck, bool printInfo); static u32 loadFirmSd(const char *filePath); bool isFirmLoaded(void) @@ -41,7 +41,7 @@ menuUpdateGlobalState(); - if(!tryLoadFirmware(filePath)) + if(!tryLoadFirmware(filePath), false, true) { if(!quick) { @@ -216,7 +216,7 @@ bool TryLoadFirmwareFromSettings(void) { const char *path; - int keyBootOption, keyPad; + int keyBootOption, keyBootMode, keyPad; int i; u32 padValue, expectedPadValue; @@ -233,6 +233,9 @@ { return false; } + + const u32 *temp = configGetData(keyBootMode); + keyBootMode = temp? *temp : BootModeNormal; keyBootOption = KBootOption1; keyPad = KBootOption1Buttons; @@ -251,7 +254,7 @@ if(!statFirmware(path)) { printf("Couldn't find firmware...\n"); - continue; + goto try_next; } // check pad value @@ -266,18 +269,24 @@ { printf("Skipping, right buttons are not pressed.\n"); printf("%" PRIX32 " %" PRIX32 "\n", padValue, expectedPadValue); - continue; + goto try_next; } } - if(tryLoadFirmware(path)) + if(tryLoadFirmware(path, false, false)) break; else { printf("Bad firmware, trying next one...\n"); - TIMER_sleep(200); } } + else + continue; + +try_next: + + if(keyBootMode != BootModeQuick) + TIMER_sleep(300); // ... we failed, try next one } @@ -295,7 +304,7 @@ return true; } -static bool tryLoadFirmware(const char *filepath) +static bool tryLoadFirmware(const char *filepath, bool skipHashCheck, bool printInfo) { u32 fw_size; @@ -312,7 +321,7 @@ if(fw_size == 0) return false; - return firm_verify(fw_size); + return firm_verify(fw_size, skipHashCheck, printInfo); } static u32 loadFirmSd(const char *filePath) diff --git a/source/arm9/menu_nand.c b/source/arm9/menu_nand.c index 0ae7319..559fb1d 100644 --- a/source/arm9/menu_nand.c +++ b/source/arm9/menu_nand.c @@ -8,6 +8,7 @@ #include "hid.h" #include "util.h" #include "arm9/menu.h" +#include "arm9/timer.h" #include "arm9/util_nand.h" @@ -124,7 +125,9 @@ fail: free(buf); - wait(0x8000000); + + printf("Press any key to return..."); + menuWaitForAnyPadkey(); menuSetReturnToState(STATE_PREVIOUS); @@ -227,7 +230,9 @@ fail: free(buf); remount_nand_fs(); - wait(0x8000000); + + printf("Press any key to return..."); + menuWaitForAnyPadkey(); menuSetReturnToState(STATE_PREVIOUS);