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;
}