diff --git a/source/installer.c b/source/installer.c
index f11ea51..06b8173 100644
--- a/source/installer.c
+++ b/source/installer.c
@@ -1,15 +1,19 @@
#include "installer.h"
#include "validator.h"
#include "safewrite.h"
+#include "chainload.h"
#include "nand.h"
#include "ui.h"
#include "qff.h"
+#include "hid.h"
#define COLOR_STATUS(s) ((s == STATUS_GREEN) ? COLOR_BRIGHTGREEN : (s == STATUS_YELLOW) ? COLOR_BRIGHTYELLOW : (s == STATUS_RED) ? COLOR_RED : COLOR_DARKGREY)
#define MIN_SD_FREE (16 * 1024 * 1024) // 16MB
#define FIRM_NAND_OFFSET 0x0B130000
#define FIRM_NAND_SIZE 0x800000
+#define FIRM0_NAND_OFFSET FIRM_NAND_OFFSET
+#define FIRM1_NAND_OFFSET (FIRM_NAND_OFFSET + (FIRM_NAND_SIZE/2))
#define NAME_SIGHAXFIRM (INPUT_PATH "/sighaxfirm.bin")
#define NAME_SIGHAXFIRMSHA (INPUT_PATH "/sighaxfirm.bin.sha")
@@ -40,27 +44,28 @@ static char msgInstall[64] = "not started";
u32 ShowInstallerStatus(void) {
const u32 pos_xb = 10;
const u32 pos_x0 = pos_xb;
- const u32 pos_x1 = pos_x0 + (16*FONT_WIDTH_EXT);
+ const u32 pos_x1 = pos_x0 + (17*FONT_WIDTH_EXT);
const u32 pos_yb = 10;
const u32 pos_y0 = pos_yb + 20;
+ const u32 stp = 12;
DrawStringF(BOT_SCREEN, pos_xb, pos_yb, COLOR_STD_FONT, COLOR_STD_BG, "SafeSigHaxInstaller v" VERSION);
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 0, COLOR_STD_FONT, COLOR_STD_BG, "ARM9LoaderHax :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 10, COLOR_STD_FONT, COLOR_STD_BG, "MicroSD Card :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 20, COLOR_STD_FONT, COLOR_STD_BG, "Sighaxed FIRM :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 30, COLOR_STD_FONT, COLOR_STD_BG, "Secret Sector :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 40, COLOR_STD_FONT, COLOR_STD_BG, "Crypto Status :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 50, COLOR_STD_FONT, COLOR_STD_BG, "Backup Status :");
- DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + 60, COLOR_STD_FONT, COLOR_STD_BG, "Install Status:");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (0*stp), COLOR_STD_FONT, COLOR_STD_BG, "ARM9LoaderHax -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (1*stp), COLOR_STD_FONT, COLOR_STD_BG, "MicroSD Card -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (2*stp), COLOR_STD_FONT, COLOR_STD_BG, "Sighaxed FIRM -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (3*stp), COLOR_STD_FONT, COLOR_STD_BG, "Secret Sector -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (4*stp), COLOR_STD_FONT, COLOR_STD_BG, "Crypto Status -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (5*stp), COLOR_STD_FONT, COLOR_STD_BG, "Backup Status -");
+ DrawStringF(BOT_SCREEN, pos_x0, pos_y0 + (6*stp), COLOR_STD_FONT, COLOR_STD_BG, "Install Status -");
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 0, COLOR_STATUS(statusA9lh) , COLOR_STD_BG, "%-22.22s", msgA9lh );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 10, COLOR_STATUS(statusSdCard) , COLOR_STD_BG, "%-22.22s", msgSdCard );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 20, COLOR_STATUS(statusFirm) , COLOR_STD_BG, "%-22.22s", msgFirm );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 30, COLOR_STATUS(statusSector) , COLOR_STD_BG, "%-22.22s", msgSector );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 40, COLOR_STATUS(statusCrypto) , COLOR_STD_BG, "%-22.22s", msgCrypto );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 50, COLOR_STATUS(statusBackup) , COLOR_STD_BG, "%-22.22s", msgBackup );
- DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + 60, COLOR_STATUS(statusInstall), COLOR_STD_BG, "%-22.22s", msgInstall);
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (0*stp), COLOR_STATUS(statusA9lh) , COLOR_STD_BG, "%-21.21s", msgA9lh );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (1*stp), COLOR_STATUS(statusSdCard) , COLOR_STD_BG, "%-21.21s", msgSdCard );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (2*stp), COLOR_STATUS(statusFirm) , COLOR_STD_BG, "%-21.21s", msgFirm );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (3*stp), COLOR_STATUS(statusSector) , COLOR_STD_BG, "%-21.21s", msgSector );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (4*stp), COLOR_STATUS(statusCrypto) , COLOR_STD_BG, "%-21.21s", msgCrypto );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (5*stp), COLOR_STATUS(statusBackup) , COLOR_STD_BG, "%-21.21s", msgBackup );
+ DrawStringF(BOT_SCREEN, pos_x1, pos_y0 + (6*stp), COLOR_STATUS(statusInstall), COLOR_STD_BG, "%-21.21s", msgInstall);
return 0;
}
@@ -132,7 +137,7 @@ u32 SafeSigHaxInstaller(void) {
// step #3 - check secret_sector.bin file
- u8 secret_sector[0x20];
+ u8 secret_sector[0x200];
if (CheckA9lh()) {
snprintf(msgSector, 64, "checking...");
statusSector = STATUS_YELLOW;
@@ -232,8 +237,68 @@ u32 SafeSigHaxInstaller(void) {
// backups done
// step #6 - install sighaxed FIRM
- ShowPrompt(false, "Install not finished - this is only a preview");
+ // ShowPrompt(false, "Install not finished - this is only a preview");
+ snprintf(msgInstall, 64, "FIRM install...");
+ statusInstall = STATUS_YELLOW;
+ ShowInstallerStatus();
+ ShowProgress(0, 0, "FIRM install");
+ do {
+ ret = SafeWriteNand(FIRM_BUFFER, FIRM0_NAND_OFFSET, firm_size, 0x06);
+ if (ret != 0) break;
+ ShowProgress(1, 2, "FIRM install (1/2)");
+ snprintf(msgInstall, 64, "FIRM install (1/2)");
+ ShowInstallerStatus();
+ ret = SafeWriteNand(FIRM_BUFFER, FIRM1_NAND_OFFSET, firm_size, 0x06);
+ if (ret != 0) break;
+ ShowProgress(1, 2, "FIRM install (2/2)");
+ snprintf(msgInstall, 64, "FIRM install (2/2)");
+ ShowInstallerStatus();
+ if (CheckA9lh()) {
+ snprintf(msgInstall, 64, "0x96 revert...");
+ ShowInstallerStatus();
+ ret = SafeWriteNand(secret_sector, 0x96, 0x200, 0x06);
+ if (ret == 0) snprintf(msgA9lh, 64, "uninstalled");
+ }
+ } while (false);
+ if (ret == 0) {
+ snprintf(msgInstall, 64, "install success!");
+ statusInstall = STATUS_GREEN;
+ return 0;
+ } else {
+ snprintf(msgInstall, 64, "install failed");
+ statusInstall = STATUS_RED;
+ if (CheckA9lh()) {
+ snprintf(msgA9lh, 64, "fucked up");
+ statusA9lh = STATUS_RED;
+ }
+ }
+ // if we end up here: uhoh
+ ShowPrompt(false, "SafeSigHaxInstaller failed!\nThis really should not have happened :/.");
+ ShowPrompt(false, "You can now load 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", "Launch " 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);
+ }
+ }
+ }
return 0;
}
diff --git a/source/main.c b/source/main.c
index b2e73be..3f80a39 100644
--- a/source/main.c
+++ b/source/main.c
@@ -1,6 +1,7 @@
#include "installer.h"
#include "ui.h"
#include "i2c.h"
+#include "qff.h"
void Reboot()
{
@@ -14,7 +15,9 @@ int main()
u32 ret = SafeSigHaxInstaller();
ShowInstallerStatus(); // update installer status one last time
if (ret) ShowPrompt(false, "SigHaxed FIRM was not installed!\nCheck lower screen for info.");
+ else ShowPrompt(false, "SigHaxed FIRM install success!");
ClearScreenF(true, true, COLOR_STD_BG);
+ fs_deinit();
Reboot();
return 0;
}
diff --git a/source/nand/nand.c b/source/nand/nand.c
index 2f21692..d803db2 100644
--- a/source/nand/nand.c
+++ b/source/nand/nand.c
@@ -172,12 +172,12 @@ bool CheckSector0x96Crypto(void)
bool CheckFirmCrypto(void)
{
// check the FIRM magic
- const u8 magic[8] = {'F', 'I', 'R', 'M', '\0', '\0', '\0', '\0'};
+ const u8 magic[8] = {'F', 'I', 'R', 'M'};
const u32 sectors[] = { SECTOR_FIRM0, SECTOR_FIRM1 };
u8 buffer[0x200];
for (u32 i = 0; i < sizeof(sectors) / sizeof(u32); i++) {
ReadNandSectors(buffer, sectors[i], 1, 0x06);
- if (memcmp(buffer, magic, 8) != 0) return false;
+ if (memcmp(buffer, magic, sizeof(magic)) != 0) return false;
}
// success if we arrive here
diff --git a/source/safety/validator.c b/source/safety/validator.c
index fa9bf5a..c108502 100644
--- a/source/safety/validator.c
+++ b/source/safety/validator.c
@@ -1,7 +1,7 @@
#include "validator.h"
#include "sha.h"
-#define FIRM_MAGIC 'F', 'I', 'R', 'M', '\0', '\0', '\0', '\0'
+#define FIRM_MAGIC 'F', 'I', 'R', 'M'
#define FIRM_MAX_SIZE 0x400000 // 4MB, due to FIRM partition size
// see: https://www.3dbrew.org/wiki/FIRM#Firmware_Section_Headers
@@ -15,7 +15,8 @@ typedef struct {
// see: https://www.3dbrew.org/wiki/FIRM#FIRM_Header
typedef struct {
- u8 magic[8];
+ u8 magic[4];
+ u8 priority[4];
u32 entry_arm11;
u32 entry_arm9;
u8 reserved1[0x30];
@@ -56,6 +57,8 @@ u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) {
u32 ValidateFirm(void* firm, u8* firm_sha, u32 firm_size, char* output) {
FirmHeader* header = (FirmHeader*) firm;
+ int section_arm11 = -1;
+ int section_arm9 = -1;
// validate firm header
if (ValidateFirmHeader(header, firm_size) != 0)
@@ -69,6 +72,18 @@ u32 ValidateFirm(void* firm, u8* firm_sha, u32 firm_size, char* output) {
if (output) snprintf(output, 64, "Section %lu hash mismatch", i);
return 1;
}
+ if ((header->entry_arm11 >= section->address) &&
+ (header->entry_arm11 < section->address + section->size))
+ section_arm11 = i;
+ if ((header->entry_arm9 >= section->address) &&
+ (header->entry_arm9 < section->address + section->size))
+ section_arm9 = i;
+ }
+
+ // sections for arm11 / arm9 entrypoints not found?
+ if ((section_arm11 < 0) || (section_arm9 < 0)) {
+ if (output) snprintf(output, 64, "ARM11/ARM9 entrypoints not found");
+ return 1;
}
// check provided .SHA
@@ -77,9 +92,6 @@ u32 ValidateFirm(void* firm, u8* firm_sha, u32 firm_size, char* output) {
return 1;
}
- // ARM9 / ARM11 area check (?)
- // more (?)
-
return 0;
}
@@ -88,7 +100,7 @@ u32 ValidateSector(void* sector) {
}
u32 CheckFirmSigHax(void* firm) {
- return 0; // not like we can check that already
+ return 0; // not like we can check that already (!!!)
FirmHeader* header = (FirmHeader*) firm;
return (sha_cmp(sighaxHash, header->signature, 0x100, SHA256_MODE) == 0) ? 0 : 1;
}