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