diff --git a/include/arm11/menu/menu_fb3ds.h b/include/arm11/menu/menu_fb3ds.h index 39334fb..98f81a9 100644 --- a/include/arm11/menu/menu_fb3ds.h +++ b/include/arm11/menu/menu_fb3ds.h @@ -71,6 +71,7 @@ #define DESC_NAND_RESTORE "Restore current NAND from a file.\nThis option preserves your fastboot3ds installation." #define DESC_NAND_RESTORE_F "Restore current NAND from a file.\nWARNING: This will overwrite all of your flash memory, also overwriting fastboot3ds." #define DESC_FIRM_FLASH "Flash firmware from file to firm1:.\nWARNING: This will allow you to flash unsigned firmware, overwriting anything previously installed in firm1:." +#define DESC_DUMP_BOOTROM "Dump boot9.bin, boot11.bin & otp.bin.\nFiles are written to sdmc:/3DS. Your console will power off when finished." #define DESC_UPDATE "Update fastboot3ds. Only signed updates are allowed." #define DESC_CREDITS "Show fastboot3ds credits." @@ -140,12 +141,13 @@ } }, { // 5 - "NAND Tools", 4, &menuPresetNandTools, 0, + "NAND Tools", 5, &menuPresetNandTools, 0, { { "Backup NAND", DESC_NAND_BACKUP, &menuBackupNand, 0 }, { "Restore NAND", DESC_NAND_RESTORE, &menuRestoreNand, 0 }, { "Restore NAND (forced)", DESC_NAND_RESTORE_F, &menuRestoreNand, 1 }, - { "Flash firmware to FIRM1", DESC_FIRM_FLASH, &menuInstallFirm, 1 } + { "Flash firmware to FIRM1", DESC_FIRM_FLASH, &menuInstallFirm, 1 }, + { "Dump bootroms & OTP", DESC_DUMP_BOOTROM, &menuDumpBootrom, 0 } } }, { // 6 diff --git a/include/arm11/menu/menu_func.h b/include/arm11/menu/menu_func.h index 54e2310..5c25d2f 100644 --- a/include/arm11/menu/menu_func.h +++ b/include/arm11/menu/menu_func.h @@ -57,6 +57,7 @@ u32 menuInstallFirm(PrintConsole* term_con, PrintConsole* menu_con, u32 param); u32 menuUpdateFastboot3ds(PrintConsole* term_con, PrintConsole* menu_con, u32 param); u32 menuShowCredits(PrintConsole* term_con, PrintConsole* menu_con, u32 param); +u32 menuDumpBootrom(PrintConsole* term_con, PrintConsole* menu_con, u32 param); // everything below has to go u32 menuDummyFunc(PrintConsole* term_con, PrintConsole* menu_con, u32 param); diff --git a/include/fsutils.h b/include/fsutils.h index 70fd493..374725c 100644 --- a/include/fsutils.h +++ b/include/fsutils.h @@ -29,3 +29,4 @@ bool fsMountSdmc(); bool fsCreateFileWithPath(const char *filepath); bool fsQuickRead(const char* filepath, void* buff, u32 len, u32 off); +bool fsQuickCreate(const char* filepath, const void *const , u32 len); diff --git a/include/mem_map.h b/include/mem_map.h index 7e2e802..9676335 100644 --- a/include/mem_map.h +++ b/include/mem_map.h @@ -89,6 +89,11 @@ #define FCRAM_N3DS_EXT_SIZE (FCRAM_SIZE) +/* OTP */ +#define OTP_BASE (0x10012000) +#define OTP_SIZE (0x00000100) // 256 byte + + #ifdef ARM9 /* DTCM */ #define DTCM_BASE (0xFFF00000) diff --git a/source/arm11/main.c b/source/arm11/main.c index 6d3ad44..b604ff1 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -21,6 +21,7 @@ #include "arm11/hardware/hid.h" #include "arm11/menu/bootslot.h" #include "arm11/menu/menu.h" +#include "arm11/menu/menu_func.h" // the bootrom dumper is in there #include "arm11/menu/menu_fb3ds.h" #include "arm11/menu/menu_util.h" #include "arm11/menu/splash.h" @@ -35,12 +36,15 @@ #include "banner_spla.h" #include "fsutils.h" +extern const bool __superhaxEnabled; + int main(void) { bool startFirmLaunch = false; bool show_menu = false; + bool dump_bootroms = __superhaxEnabled; bool gfx_initialized = false; u32 menu_ret = MENU_OK; @@ -52,6 +56,21 @@ fsMountSdmc(); fsMountNandFilesystems(); loadConfigFile(); + + + // bootrom dumper? + // skip bootslot / FCRAM / reboot handling in that case + if(dump_bootroms) + { + // workaround when HOME button is held + if (hidIsHomeButtonHeldRaw()) + { + menu_ret = MENU_RET_REBOOT; + toggleSuperhax(false); + goto menu_end; + } + goto menu_start; + } // get bootmode from config, previous bootslot from I2C @@ -159,12 +178,14 @@ } + menu_start: ; + // main loop PrintConsole term_con; while(!startFirmLaunch) { // init screens / console (if we'll need them below) - if(show_menu || err_string) + if(show_menu || err_string || dump_bootroms) { if (!gfx_initialized) GFX_init(true); gfx_initialized = true; @@ -189,6 +210,16 @@ if(hidGetPowerButton(false)) break; } + + // bootrom dumper handling + if(dump_bootroms) + { + menu_ret = menuDumpBootrom(&term_con, NULL, 0); + if ((menu_ret == MENU_RET_POWEROFF) || (menu_ret == MENU_RET_REBOOT)) + break; // success + else + show_menu = true; // backup solution + } // menu specific code if(show_menu) @@ -291,6 +322,8 @@ } } + + menu_end: // deinit GFX if it was initialized if(gfx_initialized) GFX_deinit(firm_err == 1); diff --git a/source/arm11/menu/menu_func.c b/source/arm11/menu/menu_func.c index 2afdc4e..0f59504 100644 --- a/source/arm11/menu/menu_func.c +++ b/source/arm11/menu/menu_func.c @@ -21,6 +21,10 @@ #include #include #include +// we need the ARM9 info from mem_map.h +#define ARM9 +#include "mem_map.h" +#undef ARM9 #include "types.h" #include "firmwriter.h" #include "fs.h" @@ -877,12 +881,94 @@ return result; } +u32 menuDumpBootrom(PrintConsole* term_con, PrintConsole* menu_con, u32 param) +{ + extern const bool __superhaxEnabled; + + (void) menu_con; + (void) param; + + u32 result = MENU_FAIL; + + // bootrom dumper output + consoleSelect(term_con); + consoleClear(); + ee_printf(ESC_SCHEME_ACCENT1 "Dumping Bootroms and OTP...\n\n" ESC_RESET); + + // if superhax is not enabled: enable it and reboot + // (carefull not to introduce a potential bootloop here!) + if (!__superhaxEnabled) + { + ee_printf("Enabling SuperHax... "); + s32 ret = toggleSuperhax(true); + if (ret != 0) + { + ee_printf(ESC_SCHEME_BAD "failed!\n" ESC_RESET); + if (ret == -6) + ee_printf("Fastboot3DS not installed in FIRM0.\n"); + else + ee_printf("Unknown error.\n"); + goto fail; + } + else + { + ee_printf(ESC_SCHEME_GOOD "success\n" ESC_RESET); + ee_printf("Now rebooting..."); + return MENU_RET_REBOOT; + } + } + + // if we arrive here: superhax enabled, ready to dump + bool valid; + s32 kDown; + + // dump boot9.bin + ee_printf("Dumping ARM9 bootrom... "); + valid = fsQuickCreate("sdmc:/3DS/boot9.bin", (void*) BOOT9_BASE, BOOT9_SIZE); + ee_printf(valid ? ESC_SCHEME_GOOD "success\n" ESC_RESET : ESC_SCHEME_BAD "failed!\n" ESC_RESET); + updateScreens(); + + // dump boot11.bin + ee_printf("Dumping ARM11 bootrom... "); + valid = fsQuickCreate("sdmc:/3DS/boot11.bin", (void*) (VRAM_BASE + VRAM_SIZE - BOOT11_SIZE), BOOT11_SIZE); + ee_printf(valid ? ESC_SCHEME_GOOD "success\n" ESC_RESET : ESC_SCHEME_BAD "failed!\n" ESC_RESET); + updateScreens(); + + // dump otp.bin + ee_printf("Dumping OTP... "); + valid = fsQuickCreate("sdmc:/3DS/otp.bin", (void*) OTP_BASE, OTP_SIZE); + ee_printf(valid ? ESC_SCHEME_GOOD "success\n" ESC_RESET : ESC_SCHEME_BAD "failed!\n" ESC_RESET); + updateScreens(); + + // disable superhax + ee_printf("Disabling SuperHax... "); + if (toggleSuperhax(false) != 0) + { + ee_printf(ESC_SCHEME_BAD "failed!\n" ESC_RESET); + } + else + { + ee_printf(ESC_SCHEME_GOOD "success\n" ESC_RESET); + result = MENU_RET_POWEROFF; + } + + + fail: + + ee_printf("\nPress B or HOME to %s.", (result == MENU_RET_POWEROFF) ? "power off" : "return"); + updateScreens(); + outputEndWait(); + + + return result; +} + u32 menuUpdateFastboot3ds(PrintConsole* term_con, PrintConsole* menu_con, u32 param) { (void) param; char firm_path[FF_MAX_LFN + 1]; - u32 result = 1; + u32 result = MENU_FAIL; bool accept_downgrades = false; if (configDevModeEnabled()) diff --git a/source/fsutils.c b/source/fsutils.c index 483f79c..381b7c6 100644 --- a/source/fsutils.c +++ b/source/fsutils.c @@ -151,3 +151,16 @@ fClose(fHandle); return res; } + +bool fsQuickCreate(const char* filepath, const void *const buff, u32 len) +{ + s32 fHandle = fOpen(filepath, FS_CREATE_ALWAYS | FS_OPEN_WRITE); + if (fHandle < 0) return false; + + bool res = true; + if (len && buff && fWrite(fHandle, buff, len) != 0) + res = false; + + fClose(fHandle); + return res; +}