Line 1:
Line 1:
Just like it's Wii counterpart, boot1 is the second-stage bootloader which is loaded by [[boot0]].
Just like it's Wii counterpart, boot1 is the second-stage bootloader which is loaded by [[boot0]].
−
boot1 is stored inside the first SLC NAND blocks in the form of an [[Ancast_Image | ancast image]]. There are always two copies of boot1 inside the SLC NAND and, together, these images form the only blocks that are left as plain data (not encrypted with the OTP SLC key).
+
boot1 is stored inside the first SLC NAND blocks in the form of an [[Ancast_Image|ancast image]]. There are always two copies of boot1 inside the SLC NAND and, together, these images form the only blocks that are left as plain data (not encrypted with the OTP SLC key).
boot1 runs from on-die SRAM starting at address 0x0D400000 and it's size must not exceed the total of 0xF800 bytes (it's size is checked by boot0).
boot1 runs from on-die SRAM starting at address 0x0D400000 and it's size must not exceed the total of 0xF800 bytes (it's size is checked by boot0).
−
During the boot process, boot0 loads boot1 from NAND and decrypts it using an AES key stored in the console's [[Hardware/OTP | OTP]]. Immediately after, boot0 permanently disables access to this key by clearing the appropriate value in the [[Hardware/Latte_Registers#LT_OTPPROT | LT_OTPPROT]] register.
+
During the boot process, boot0 loads boot1 from NAND and decrypts it using an AES key stored in the console's [[Hardware/OTP|OTP]]. Immediately after, boot0 permanently disables access to this key by clearing the appropriate value in the [[Hardware/Latte_Registers#LT_OTPPROT|LT_OTPPROT]] register.
What follows are general descriptions and pseudo-code that illustrates the several sub-stages of the Wii U's boot1.
What follows are general descriptions and pseudo-code that illustrates the several sub-stages of the Wii U's boot1.
Line 36:
Line 36:
// Get timer value
// Get timer value
−
u32 time_boot1_start = *(u32 *)LT_TIMER;
+
u32 time_boot1_start = *(u32 *)HW_TIMER;
// Clear NDEV_LED state
// Clear NDEV_LED state
*(u32 *)(0x0D40E258) = 0;
*(u32 *)(0x0D40E258) = 0;
−
u32 boot0_val = *(u32 *)LT_BOOT0;
+
u32 spare1_val = *(u32 *)HW_SPARE1;
// Disable boot0 mapping
// Disable boot0 mapping
−
*(u32 *)LT_BOOT0 = boot0_val | 0x1000;
+
*(u32 *)HW_SPARE1 = spare1_val | 0x1000;
// Assert RSTB_IOPI and RSTB_IOMEM
// Assert RSTB_IOPI and RSTB_IOMEM
−
u32 resets_compat_val = *(u32 *)LT_RESETS_COMPAT;
+
u32 resets_val = *(u32 *)HW_RSTB;
−
resets_compat_val &= 0xFFF7FFFF;
+
resets_val &= 0xFFF7FFFF;
−
resets_compat_val |= 0x80000;
+
resets_val |= 0x80000;
−
resets_compat_val &= 0xFFFBFFFF;
+
resets_val &= 0xFFFBFFFF;
−
resets_compat_val |= 0x40000;
+
resets_val |= 0x40000;
−
*(u32 *)LT_RESETS_COMPAT = resets_compat_val;
+
*(u32 *)HW_RSTB= resets_val;
// Enable EXI
// Enable EXI
−
u32 exictrl_val = *(u32 *)LT_EXICTRL;
+
u32 aip_prot_val = *(u32 *)HW_AIP_PROT;
−
exictrl_val &= ~(0x01);
+
aip_prot_val &= ~(0x01);
−
exictrl_val |= 0x01;
+
aip_prot_val |= 0x01;
−
*(u32 *)LT_EXICTRL = exictrl_val;
+
*(u32 *)HW_AIP_PROT = aip_prot_val;
=== check_hw ===
=== check_hw ===
Line 86:
Line 86:
if (iop2x_val & 0x04)
if (iop2x_val & 0x04)
{
{
−
// Enable SYSPROT IRQ
+
// Enable IRQ 12 (LT)
−
*(u32 *)LT_INTSR_AHBLT_ARM = 0x1000;
+
*(u32 *)LT_ARMIRQFLAGLT = 0x1000;
−
*(u32 *)LT_INTMR_AHBLT_ARM = 0x1000;
+
*(u32 *)LT_ARMIRQMASKLT = 0x1000;
// Switch the multiplier back to 1x
// Switch the multiplier back to 1x
Line 96:
Line 96:
sub_D40C870();
sub_D40C870();
−
// Disable SYSPROT IRQ
+
// Disable IRQ 12 (LT)
*(u32 *)LT_INTMR_AHBLT_ARM = 0;
*(u32 *)LT_INTMR_AHBLT_ARM = 0;
}
}
Line 196:
Line 196:
u32 state_flag = 0;
u32 state_flag = 0;
−
// Check some debug flag
+
// Check if the CMPT_RETSTAT0 flag is raised
if (debug_val & 0x04)
if (debug_val & 0x04)
state_flag = 0x100000;
state_flag = 0x100000;
−
// Check some debug flag
+
// Check if the CMPT_RETSTAT1 flag is raised
if (debug_val & 0x08)
if (debug_val & 0x08)
state_flag |= 0x80000;
state_flag |= 0x80000;
Line 426:
Line 426:
if (!(iop2x_val & 0x04))
if (!(iop2x_val & 0x04))
{
{
−
// Enable SYSPROT IRQ
+
// Enable IRQ 12 (LT)
−
*(u32 *)LT_INTSR_AHBLT_ARM = 0x1000;
+
*(u32 *)LT_ARMIRQFLAGLT = 0x1000;
−
*(u32 *)LT_INTMR_AHBLT_ARM = 0x1000;
+
*(u32 *)LT_ARMIRQMASKLT = 0x1000;
// Change IOP clock multiplier to 3x
// Change IOP clock multiplier to 3x
Line 436:
Line 436:
sub_D40C870();
sub_D40C870();
−
// Disable SYSPROT IRQ
+
// Disable IRQ 12 (LT)
−
*(u32 *)LT_INTMR_AHBLT_ARM = 0;
+
*(u32 *)LT_ARMIRQMASKLT = 0;
}
}
}
}
Line 512:
Line 512:
// Get timer value
// Get timer value
−
u32 time_before_fw_load = *(u32 *)LT_TIMER;
+
u32 time_before_fw_load = *(u32 *)HW_TIMER;
// Load fw.img
// Load fw.img
Line 527:
Line 527:
// Get timer value
// Get timer value
−
u32 time_after_fw_load = *(u32 *)LT_TIMER;
+
u32 time_after_fw_load = *(u32 *)HW_TIMER;
u32 time_fw_verify = 0;
u32 time_fw_verify = 0;
Line 535:
Line 535:
{
{
// Get timer value
// Get timer value
−
u32 time_before_fw_verify = *(u32 *)LT_TIMER;
+
u32 time_before_fw_verify = *(u32 *)HW_TIMER;
// Initialize SHA-1 engine 1 (SHA)
// Initialize SHA-1 engine 1 (SHA)
Line 869:
Line 869:
// Get timer value
// Get timer value
−
u32 time_after_fw_verify = *(u32 *)LT_TIMER;
+
u32 time_after_fw_verify = *(u32 *)HW_TIMER;
−
u32 time_before_fw_decrypt = *(u32 *)LT_TIMER;
+
u32 time_before_fw_decrypt = *(u32 *)HW_TIMER;
u32 starbuck_ancast_iv_addr = 0x0D40DAC0;
u32 starbuck_ancast_iv_addr = 0x0D40DAC0;
Line 947:
Line 947:
// Get timer value
// Get timer value
−
u32 time_boot1_end = *(u32 *)LT_TIMER;
+
u32 time_boot1_end = *(u32 *)HW_TIMER;
// Calculate time spent running boot1
// Calculate time spent running boot1