Improved ntrboot checks

... this also restores default behaviour when booting from ntrboot and
simplifies the bootloader behaviour.
This commit is contained in:
d0k3 2017-09-23 13:09:50 +02:00
parent a92c993573
commit dcafbaa191
8 changed files with 44 additions and 16 deletions

View File

@ -32,8 +32,6 @@ To build a .firm signed with SPI boot keys (for ntrboot and the like), run `make
## Bootloader mode / NTRboot mode ## 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)*. 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 ## 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. 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.

View File

@ -13,5 +13,5 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__stack_top = 0x1FFFF800; __stack_top = 0x1FFFE000;
} }

View File

@ -9,9 +9,6 @@
// see: https://www.3dbrew.org/wiki/OTP_Registers#Plaintext_OTP // see: https://www.3dbrew.org/wiki/OTP_Registers#Plaintext_OTP
#define IS_DEVKIT ((*(vu8*) (0x01FFB800+0x19)) != 0x0) #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 // see: https://3dbrew.org/wiki/CONFIG11_Registers
// (also returns true for sighaxed systems, maybe change the name later?) // (also returns true for sighaxed systems, maybe change the name later?)
#define IS_A9LH ((*(vu32*) 0x101401C0) == 0) #define IS_A9LH ((*(vu32*) 0x101401C0) == 0)

View File

@ -1638,9 +1638,9 @@ u32 GodMode(bool is_b9s) {
u32 cursor = 0; u32 cursor = 0;
u32 scroll = 0; u32 scroll = 0;
bool bootloader = !is_b9s && IS_SIGHAX; // only when installed to FIRM / on NTRBOOT u32 boot_origin = GetBootOrigin();
bool ntrboot = bootloader && IS_NTRBOOT; bool bootloader = !is_b9s && IS_SIGHAX && (boot_origin & BOOT_NAND);
bool bootmenu = bootloader && (ntrboot || CheckButton(BOOTMENU_KEY)); bool bootmenu = bootloader && CheckButton(BOOTMENU_KEY);
bool godmode9 = !bootloader; bool godmode9 = !bootloader;
FirmHeader* firm_in_mem = (FirmHeader*) DIR_BUFFER; FirmHeader* firm_in_mem = (FirmHeader*) DIR_BUFFER;
memcpy(firm_in_mem, "NOPE", 4); // to prevent bootloops memcpy(firm_in_mem, "NOPE", 4); // to prevent bootloops
@ -1653,11 +1653,12 @@ u32 GodMode(bool is_b9s) {
} }
} }
const char* disp_mode = // get mode string for splash screen
ntrboot ? "ntrboot mode" : const char* disp_mode = NULL;
bootmenu ? "bootmenu mode" : if (bootloader) disp_mode = "bootloader mode";
bootloader ? "bootloader mode" : else if (!is_b9s && !IS_SIGHAX) disp_mode = "oldloader mode";
!is_b9s ? "oldloader mode" : NULL; 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); ClearScreenF(true, true, COLOR_STD_BG);
SplashInit(disp_mode); SplashInit(disp_mode);
@ -1703,6 +1704,7 @@ u32 GodMode(bool is_b9s) {
} }
#ifndef AL3X10MODE #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 while (HID_STATE & BUTTON_ANY); // don't continue while any button is held
#endif #endif
while (timer_msec( timer ) < 500); // show splash for at least 0.5 sec while (timer_msec( timer ) < 500); // show splash for at least 0.5 sec

View File

@ -534,6 +534,30 @@ u32 GetNandPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 ind
return 0; 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) bool CheckMultiEmuNand(void)
{ {
// this only checks for the theoretical possibility // this only checks for the theoretical possibility

View File

@ -7,6 +7,11 @@
#define NAND_IMGNAND (1UL<<2) #define NAND_IMGNAND (1UL<<2)
#define NAND_ZERONAND (1UL<<3) #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 // hardcoded start sectors
#define SECTOR_D0K3 0x000001 #define SECTOR_D0K3 0x000001
#define SECTOR_SECRET 0x000096 #define SECTOR_SECRET 0x000096
@ -74,6 +79,7 @@ u32 GetNandMinSizeSectors(u32 nand_src);
u32 GetNandSizeSectors(u32 nand_src); u32 GetNandSizeSectors(u32 nand_src);
u32 GetNandNcsdPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 index, NandNcsdHeader* ncsd); 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 GetNandPartitionInfo(NandPartitionInfo* info, u32 type, u32 subtype, u32 index, u32 nand_src);
u32 GetBootOrigin(void);
u32 ValidateSecretSector(u8* sector); u32 ValidateSecretSector(u8* sector);
bool CheckMultiEmuNand(void); bool CheckMultiEmuNand(void);

View File

@ -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) 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 // 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; if (strncasecmp(path, "S:/agbsave.bin", 256) == 0) *(u32*) 0x10010000 = 0x7;
return 0; return 0;

View File

@ -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("NULL", ""); // this one is special and should not be changed later
set_var("CURRDIR", curr_dir); // script path, never changes set_var("CURRDIR", curr_dir); // script path, never changes
set_var("GM9OUT", OUTPUT_PATH); // output 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("ONTYPE", IS_O3DS ? "O3DS" : "N3DS"); // type of the console
set_var("RDTYPE", IS_DEVKIT ? "devkit" : "retail"); // devkit / retail set_var("RDTYPE", IS_DEVKIT ? "devkit" : "retail"); // devkit / retail
upd_var(NULL); // set all dynamic environment vars upd_var(NULL); // set all dynamic environment vars