From dcafbaa191f638a4765ba2d7e95639ba47f6e216 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Sat, 23 Sep 2017 13:09:50 +0200 Subject: [PATCH] Improved ntrboot checks ... this also restores default behaviour when booting from ntrboot and simplifies the bootloader behaviour. --- README.md | 2 -- screeninit/linker.ld | 2 +- source/common/unittype.h | 3 --- source/godmode.c | 18 ++++++++++-------- source/nand/nand.c | 24 ++++++++++++++++++++++++ source/nand/nand.h | 6 ++++++ source/utils/nandutil.c | 2 +- source/utils/scripting.c | 3 ++- 8 files changed, 44 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index bad016e..e1fe30d 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,6 @@ To build a .firm signed with SPI boot keys (for ntrboot and the like), run `make ## Bootloader mode / NTRboot mode Same as [boot9strap](https://github.com/SciresM/boot9strap), GodMode9 can be installed to the system FIRM partition ('FIRM0'). When executed from a FIRM partition, GodMode9 will default to bootloader mode and try to boot, in order, `FIRM from FCRAM` (see [A9NC](https://github.com/d0k3/A9NC/releases), `0:/bootonce.firm` (will be deleted on a successful boot), `0:/boot.firm`, `1:/boot.firm`. In bootloader mode, hold R+LEFT on boot to enter the boot menu. *Installing GodMode9 to a FIRM partition is only recommended for developers and will overwrite [boot9strap](https://github.com/SciresM/boot9strap)*. -When flashed directly to a [NTRboot](https://github.com/kitling/ntrboot_flasher) compatible flashcard, GodMode9 will default to ntrboot mode, which is the same as bootloader mode but automatically enters the boot menu. - ## Write permissions system GodMode9 provides a write permissions system, which will protect you from accidentually damaging you system, losing data and/or modifying important system data. To unlock a write permission, an unlock sequence must be entered. This is not possible by accident. The write permission system is based on colors and the top bar on the top screen will change color according to the current write permission level. No permission above the yellow level can be unlocked on SafeMode9. diff --git a/screeninit/linker.ld b/screeninit/linker.ld index 801211c..f2cdb5b 100644 --- a/screeninit/linker.ld +++ b/screeninit/linker.ld @@ -13,5 +13,5 @@ SECTIONS . = ALIGN(4); - __stack_top = 0x1FFFF800; + __stack_top = 0x1FFFE000; } diff --git a/source/common/unittype.h b/source/common/unittype.h index 6867a5a..9a53881 100644 --- a/source/common/unittype.h +++ b/source/common/unittype.h @@ -9,9 +9,6 @@ // see: https://www.3dbrew.org/wiki/OTP_Registers#Plaintext_OTP #define IS_DEVKIT ((*(vu8*) (0x01FFB800+0x19)) != 0x0) -// check first 8 byte of NTRBOOT blowfish data (0x6A0 in DTCM) -#define IS_NTRBOOT ((*(vu64*) (0x300086A0)) == 0xBFEFD1CD2683A24E) - // see: https://3dbrew.org/wiki/CONFIG11_Registers // (also returns true for sighaxed systems, maybe change the name later?) #define IS_A9LH ((*(vu32*) 0x101401C0) == 0) diff --git a/source/godmode.c b/source/godmode.c index 6429736..2457b99 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -1638,9 +1638,9 @@ u32 GodMode(bool is_b9s) { u32 cursor = 0; u32 scroll = 0; - bool bootloader = !is_b9s && IS_SIGHAX; // only when installed to FIRM / on NTRBOOT - bool ntrboot = bootloader && IS_NTRBOOT; - bool bootmenu = bootloader && (ntrboot || CheckButton(BOOTMENU_KEY)); + u32 boot_origin = GetBootOrigin(); + bool bootloader = !is_b9s && IS_SIGHAX && (boot_origin & BOOT_NAND); + bool bootmenu = bootloader && CheckButton(BOOTMENU_KEY); bool godmode9 = !bootloader; FirmHeader* firm_in_mem = (FirmHeader*) DIR_BUFFER; memcpy(firm_in_mem, "NOPE", 4); // to prevent bootloops @@ -1653,11 +1653,12 @@ u32 GodMode(bool is_b9s) { } } - const char* disp_mode = - ntrboot ? "ntrboot mode" : - bootmenu ? "bootmenu mode" : - bootloader ? "bootloader mode" : - !is_b9s ? "oldloader mode" : NULL; + // get mode string for splash screen + const char* disp_mode = NULL; + if (bootloader) disp_mode = "bootloader mode"; + else if (!is_b9s && !IS_SIGHAX) disp_mode = "oldloader mode"; + else if (!is_b9s && IS_SIGHAX && (boot_origin & BOOT_NTRBOOT)) disp_mode = "ntrboot mode"; + // else if (!is_b9s || !IS_SIGHAX) disp_mode = "unknown mode"; ClearScreenF(true, true, COLOR_STD_BG); SplashInit(disp_mode); @@ -1703,6 +1704,7 @@ u32 GodMode(bool is_b9s) { } #ifndef AL3X10MODE + bootmenu = bootloader && CheckButton(BOOTMENU_KEY); // second check for boot menu keys while (HID_STATE & BUTTON_ANY); // don't continue while any button is held #endif while (timer_msec( timer ) < 500); // show splash for at least 0.5 sec diff --git a/source/nand/nand.c b/source/nand/nand.c index f36cff8..99636f5 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -534,6 +534,30 @@ u32 GetNandPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 ind return 0; } +u32 GetBootOrigin(void) +{ + // see: https://github.com/AuroraWright/Luma3DS/blob/bc1aa15dd709a703b9af1a0f89ccded21fc08823/source/main.c#L58-L62 + // and: https://www.3dbrew.org/wiki/Bootloader#BootROM_Errors + const vu8* bootMediaStatus = (vu8*) 0x1FFFE00C; + const vu8* bootNcsdStatus = (vu8*) 0x1FFFE010; + + if (!*(u64*) (void*) bootNcsdStatus) { // no NAND boot + bool ntrboot_ok = !(bootMediaStatus[1]); + bool shell_closed = (bootMediaStatus[3] == 2); // unsure of meaning(!) + if (ntrboot_ok && shell_closed) return BOOT_NTRBOOT; + } else if (!bootMediaStatus[0]) { // NAND boot okay, check partitions boot state + int n_boot_firm = -1; + for (u32 i = 0; i < 8; i++) { + if (bootNcsdStatus[i] != 0) continue; // not booted from here, continue + if (n_boot_firm >= 0) return BOOT_UNKNOWN; // booted from 2+ partitions? + n_boot_firm = i; + } + if (n_boot_firm >= 0) return BOOT_NAND; + } + + return BOOT_UNKNOWN; +} + bool CheckMultiEmuNand(void) { // this only checks for the theoretical possibility diff --git a/source/nand/nand.h b/source/nand/nand.h index 7db6015..184e9da 100644 --- a/source/nand/nand.h +++ b/source/nand/nand.h @@ -7,6 +7,11 @@ #define NAND_IMGNAND (1UL<<2) #define NAND_ZERONAND (1UL<<3) +#define BOOT_UNKNOWN 0 +#define BOOT_NAND (1UL<<0) +#define BOOT_NTRBOOT (1UL<<1) +#define BOOT_WIFI_SPI (1UL<<2) + // hardcoded start sectors #define SECTOR_D0K3 0x000001 #define SECTOR_SECRET 0x000096 @@ -74,6 +79,7 @@ u32 GetNandMinSizeSectors(u32 nand_src); u32 GetNandSizeSectors(u32 nand_src); u32 GetNandNcsdPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 index, NandNcsdHeader* ncsd); u32 GetNandPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 index, u32 nand_src); +u32 GetBootOrigin(void); u32 ValidateSecretSector(u8* sector); bool CheckMultiEmuNand(void); diff --git a/source/utils/nandutil.c b/source/utils/nandutil.c index 3745de4..6ef1bb5 100644 --- a/source/utils/nandutil.c +++ b/source/utils/nandutil.c @@ -175,7 +175,7 @@ u32 InjectGbaVcSavegame(const char* path, const char* path_vcsave) { if (FixFileCmac(path) != 0) return 1; // cmac fail (this is not efficient, but w/e) // set CFG_BOOTENV to 0x7 so the save is taken over - // https://www.3dbrew.org/wiki/CONFIG_Registers#CFG_BOOTENV + // https://www.3dbrew.org/wiki/CONFIG9_Registers#CFG9_BOOTENV if (strncasecmp(path, "S:/agbsave.bin", 256) == 0) *(u32*) 0x10010000 = 0x7; return 0; diff --git a/source/utils/scripting.c b/source/utils/scripting.c index 5e29701..5a32af1 100644 --- a/source/utils/scripting.c +++ b/source/utils/scripting.c @@ -353,7 +353,8 @@ bool init_vars(const char* path_script) { set_var("NULL", ""); // this one is special and should not be changed later set_var("CURRDIR", curr_dir); // script path, never changes set_var("GM9OUT", OUTPUT_PATH); // output path, never changes - set_var("HAX", IS_NTRBOOT ? "ntrboot" : IS_SIGHAX ? "sighax" : IS_A9LH ? "a9lh" : ""); // type of hax running from + set_var("HAX", ((GetBootOrigin() & BOOT_NTRBOOT) && IS_SIGHAX) ? "ntrboot" : + IS_SIGHAX ? "sighax" : IS_A9LH ? "a9lh" : ""); // type of hax running from set_var("ONTYPE", IS_O3DS ? "O3DS" : "N3DS"); // type of the console set_var("RDTYPE", IS_DEVKIT ? "devkit" : "retail"); // devkit / retail upd_var(NULL); // set all dynamic environment vars