diff --git a/source/common/chainload.h b/source/common/chainload.h deleted file mode 100644 index 7b2dc1d..0000000 --- a/source/common/chainload.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "common.h" - -#define PAYLOAD_MAX_SIZE 0xFFFE0 - -void Chainload(u8 *source, size_t size); diff --git a/source/common/chainload.s b/source/common/chainload.s deleted file mode 100644 index 426ec2a..0000000 --- a/source/common/chainload.s +++ /dev/null @@ -1,52 +0,0 @@ -@ Wolfvak - 25/01/2017 - -@ TODO: ELF launcher -@ void Chainload(u8 *source, size_t size) -@ Wrapper around chainload_itcm - -.arm -.global Chainload -.type Chainload, %function -Chainload: - ldr r2, =0x1FF8100 @ ITCM + 0x100 bytes - mov r3, r2 - ldr r4, =chainload_itcm - ldr r5, =chainload_itcm_end - -.copy_chainloader: - cmp r4, r5 - ldrlt r6, [r4], #4 - strlt r6, [r3], #4 - blt .copy_chainloader - - bx r2 @ Branch to the real chainloader in ITCM - - -@ void chainload_itcm(void) -@ Note: Uses unprotected bootrom functions -.arm -.type chainload_itcm, %function -.align 4 -chainload_itcm: - mov r2, r1 - ldr r1, =0x23F00000 - - mov r4, r1 @ memcpy256 and clean_flush_cache mess with the registers - - ldr r3, =0xFFFF03F0 @ memcpy256(u32 *src, u32 *ddest, size_t size) - blx r3 - - ldr r3, =0xFFFF0830 @ void clean_flush_cache(void) - blx r3 - - mov r3, r4 - - mov r0, #0 @ Clear argc - mov r1, #0 @ Same for argv - mov r2, #0 - mov lr, #0 - bx r3 - -.pool - -chainload_itcm_end: diff --git a/source/common/common.h b/source/common/common.h index 5807308..fa2ba50 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -41,7 +41,7 @@ #define ENTRY_GATEWAY (2) // SafeB9SInstaller version -#define VERSION "0.0.5" +#define VERSION "0.0.6" // testfing flags, only useful to devs // #define NO_WRITE // disables all NAND writes, just for testing diff --git a/source/installer.c b/source/installer.c index 5a475c3..4c73041 100644 --- a/source/installer.c +++ b/source/installer.c @@ -1,7 +1,6 @@ #include "installer.h" -#include "validator.h" #include "safewrite.h" -#include "chainload.h" +#include "validator.h" #include "nand.h" #include "ui.h" #include "qff.h" @@ -20,6 +19,7 @@ #define NAME_SECTOR0x96 (IS_DEVKIT ? INPUT_PATH "/secret_sector_dev.bin" : INPUT_PATH "/secret_sector.bin") #define NAME_FIRMBACKUP INPUT_PATH "/firm0firm1.bak" #define NAME_SECTORBACKUP INPUT_PATH "/sector0x96.bak" +#define NAME_PAYLOAD INPUT_PATH "/payload.firm" #define STATUS_GREY -1 #define STATUS_GREEN 0 @@ -294,30 +294,52 @@ u32 SafeB9SInstaller(void) { // if we end up here: uhoh ShowPrompt(false, "SafeB9SInstaller failed!\nThis really should not have happened :/."); - ShowPrompt(false, "You may launch an external payload\nto try and fix up your system.\n \nThis may be your LAST CHANCE!\nUse it wisely."); - const char* optionstr[2] = { "Unmount SD card", "Run " INPUT_PATH "/payload.bin" }; - while (true) { - u32 user_select = ShowSelectPrompt(2, optionstr, "Make your choice."); - if (user_select == 1) { - fs_deinit(); - ShowString("SD card unmounted, you can eject now.\n \n to remount SD card"); - while (true) { - u32 pad_choice = InputWait(); - if (!(pad_choice & BUTTON_A)) continue; - if (fs_init() == FR_OK) break; - ShowString("Reinitialising SD card failed!\n \n to retry"); - } - } else if (user_select == 2) { - UINT payload_size; - if ((f_qread(INPUT_PATH "/payload.bin", WORK_BUFFER, 0, WORK_BUFFER_SIZE, &payload_size) != FR_OK) || - !payload_size || (payload_size > PAYLOAD_MAX_SIZE)) - continue; - if (ShowUnlockSequence(3, "payload.bin (%dkB)\nLaunch as arm9 payload?", payload_size / 1024)) { - Chainload(WORK_BUFFER, payload_size); - while(1); - } - } - } + ShowPrompt(false, "Your system is now reverted to\nit's earlier state.\n \nDO NOT TURN OFF YOUR 3DS NOW!"); - return 0; + // try to revert to the earlier state + snprintf(msgBackup, 64, "FIRM restore..."); + statusBackup = STATUS_YELLOW; + ShowInstallerStatus(); + if (f_open(&fp, NAME_FIRMBACKUP, FA_READ|FA_OPEN_EXISTING) != FR_OK) { + snprintf(msgBackup, 64, "FIRM restore fail"); + statusBackup = STATUS_RED; + return 1; + } + ShowProgress(0, 0, "FIRM restore"); + for (u32 pos = 0; (pos < FIRM_NAND_SIZE) && (ret == 0); pos += WORK_BUFFER_SIZE) { + UINT bytes = min(WORK_BUFFER_SIZE, FIRM_NAND_SIZE - pos); + snprintf(msgBackup, 64, "FIRM restore (%luMB/%luMB)", + pos / (1024*1024), (u32) FIRM_NAND_SIZE / (1024 * 1024)); + ShowInstallerStatus(); + if ((f_read(&fp, WORK_BUFFER, bytes, &bt) != FR_OK) || (bt != bytes) || + (WriteNandBytes(WORK_BUFFER, FIRM_NAND_OFFSET + pos, bytes, 0xFF) != 0)) + ret = 1; + ShowProgress(pos + bytes, FIRM_NAND_SIZE, "FIRM restore"); + } + f_close(&fp); + if (ret != 0) { + snprintf(msgBackup, 64, "FIRM restore fail"); + statusBackup = STATUS_RED; + return 1; + } + if ((IS_A9LH && !IS_SIGHAX)) { + snprintf(msgBackup, 64, "0x96 restore..."); + ShowInstallerStatus(); + u8 sector_backup[0x200]; + if ((f_qread(NAME_SECTORBACKUP, sector_backup, 0, 0x200, &bt) != FR_OK) || (bt != 0x200) || + (WriteNandSectors(sector_backup, 0x96, 1, 0xFF) != 0)) { + snprintf(msgBackup, 64, "0x96 restore fail"); + statusBackup = STATUS_RED; + return 1; + } + snprintf(msgA9lh, 64, "restored a9lh"); + statusA9lh = STATUS_YELLOW; + } + snprintf(msgBackup, 64, "backup restored"); + statusBackup = STATUS_YELLOW; + snprintf(msgInstall, 64, "reverted system"); + statusInstall = STATUS_YELLOW; + + + return 1; }