Changes

Jump to navigation Jump to search
5,444 bytes added ,  17:04, 31 May 2020
Line 1: Line 1: −
Present on the firmware package titles (0100000000000819 and 010000000000081A) and installed into eMMC storage's [[Flash_Filesystem#Boot_Partitions|boot partitions 0 and 1]], "package1" contains the first Switch bootloader to run under the NVIDIA boot processor (an ARM7TDMI called "BPMP", "BPMP-Lite", "AVP" or "COP").
+
Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#Boot_Partitions|boot partitions 0 and 1]], "package1" contains the first Switch bootloader ("Package1ldr") to run under the NVIDIA boot processor (an ARM7TDMI called "BPMP", "BPMP-Lite", "AVP" or "COP"), as well as the actual encrypted package1 ("PK11") blob containing the second Switch Bootloader and TrustZone code.
    
The boot ROM validates, copies to IRAM and executes this package by parsing it's information block from the [[BCT|BCT]].
 
The boot ROM validates, copies to IRAM and executes this package by parsing it's information block from the [[BCT|BCT]].
   −
= Bootloader =
+
= Format =
Split into two main stages, the bootloader is responsible for setting up hardware, generate keys and prepare the main CPU ("CCPLEX").
+
== Erista ==
 +
This package is distributed as a plaintext initial bootloader (package1ldr) and a secondary encrypted blob ("PK11"). Execution starts at plaintext package1ldr which will set up hardware, generate keys and decrypt the next stage.
   −
== Stage 0 ==
+
=== Header ===
The code for this stage is stored in plaintext inside the package. By looking into the BCT's bootloader0_info (normal) or bootloader1_info (safe mode), the boot ROM starts executing this stage at address 0x40010020 in IRAM.
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x4
 +
| Package1ldr hash (first four bytes of SHA256(package1ldr))
 +
|-
 +
| 0x4
 +
| 0x4
 +
| Secure Monitor hash (first four bytes of SHA256(secure_monitor))
 +
|-
 +
| 0x8
 +
| 0x4
 +
| NX Bootloader hash (first four bytes of SHA256(nx_bootloader))
 +
|-
 +
| 0xC
 +
| 0x4
 +
| Build ID
 +
|-
 +
| 0x10
 +
| 0xE
 +
| Build Timestamp (yyyyMMddHHmmss)
 +
|-
 +
| 0x1E
 +
| 0x2
 +
| Version
 +
|}
   −
=== Initialization ===
+
=== Package1ldr ===
 +
The code for this stage is stored in plaintext inside the package. By looking into the BCT's bootloader0_info (normal) or bootloader1_info (safe mode), the boot ROM starts executing this stage at address 0x40010020 in IRAM (0x40010040 for 4.0.0+).
 +
 
 +
==== Initialization ====
 
The stack pointer is set.
 
The stack pointer is set.
    +
<syntaxhighlight lang="c">
 
  // Set the stack pointer
 
  // Set the stack pointer
 
  *(u32 *)sp = 0x40008000;
 
  *(u32 *)sp = 0x40008000;
Line 20: Line 54:  
  // Infinite loop
 
  // Infinite loop
 
  deadlock();
 
  deadlock();
 +
</syntaxhighlight>
   −
=== Main ===
+
==== Main ====
 
The bootloader poisons the exception vectors, cleans up memory (.bss and init_array), sets up hardware devices (including the security engine and fuses), does all the necessary checks, generates keys and finally decrypts and executes the next stage.
 
The bootloader poisons the exception vectors, cleans up memory (.bss and init_array), sets up hardware devices (including the security engine and fuses), does all the necessary checks, generates keys and finally decrypts and executes the next stage.
    +
<syntaxhighlight lang="c">
 
  // Poison all exception vectors
 
  // Poison all exception vectors
 
  *(u32 *)0x6000F200 = panic();
 
  *(u32 *)0x6000F200 = panic();
Line 60: Line 96:  
   
 
   
 
  // Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC
 
  // Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC
  enable_hw_devices();
+
  mbist_workaround();
 
   
 
   
 
  // Program the SE clock and resets
 
  // Program the SE clock and resets
Line 100: Line 136:  
  keygen(bct_iram_addr);
 
  keygen(bct_iram_addr);
 
   
 
   
  u32 stage1_addr = 0x40013FE0;
+
  u32 pk11_blob_addr = 0x40013FE0;
 
   
 
   
  // Decrypt next stage
+
  // Decrypt the PK11 blob and get the next stage's entrypoint
  stage1_addr = decrypt_stage1(stage1_addr);
+
  nx_boot_addr = decrypt_pk11_blob(pk11_blob_addr);
 
   
 
   
  u32 stage1_sp = 0x40007000;
+
  u32 nx_boot_sp = 0x40007000;
 
   
 
   
 
  // Set the stack pointer and jump to a stub responsible
 
  // Set the stack pointer and jump to a stub responsible
  // for cleaning up and branching into the actual stage 1
+
  // for cleaning up and branching into the next stage
  exec_stage1_stub(stage1_addr, stage1_stub_addr, stage1_sp);
+
  exec_nx_boot_stub(nx_boot_addr, nx_boot_stub_addr, nx_boot_sp);
 
   
 
   
 
  return;
 
  return;
 +
</syntaxhighlight>
   −
==== Panic ====
+
[6.2.0+] The bootloader maintains most of its design, but passes execution to a [[TSEC]] payload and is left in an infinite loop.
 +
 
 +
<syntaxhighlight lang="c">
 +
// Poison all exception vectors
 +
*(u32 *)0x6000F200 = panic();
 +
*(u32 *)0x6000F204 = panic();
 +
*(u32 *)0x6000F208 = panic();
 +
*(u32 *)0x6000F20C = panic();
 +
*(u32 *)0x6000F210 = panic();
 +
*(u32 *)0x6000F214 = panic();
 +
*(u32 *)0x6000F218 = panic();
 +
*(u32 *)0x6000F21C = panic();
 +
 +
u32 bss_addr_end = bss_addr_start;
 +
u32 bss_offset = 0;
 +
u32 bss_size = bss_addr_end - bss_addr_start;
 +
 +
// Clear .bss region
 +
// Never happens due to bss_size being set to 0
 +
while (bss_offset < bss_size)
 +
{
 +
    *(u32 *)bss_addr_start + bss_offset = 0;
 +
    bss_offset += 0x04;
 +
}
 +
 +
u32 init_array_addr_end = init_array_addr_start;
 +
u32 init_array_offset = init_array_addr_start;
 +
 +
// Call init methods
 +
// Never happens due to init_array_addr_end being set to init_array_addr_start
 +
while (init_array_offset < init_array_addr_end)
 +
{
 +
    u32 init_method_offset = *(u32 *)init_array_offset;
 +
 +
    call_init_method(init_method_offset + init_array_offset);
 +
    init_array_offset += 0x04;
 +
}
 +
 +
// Setup I2S1, I2S2, I2S3, I2S4, DISPLAY and VIC
 +
mbist_workaround();
 +
 +
// Program the SE clock and resets
 +
// Uses RST_DEVICES_V, CLK_OUT_ENB_V, CLK_SOURCE_SE and CLK_V_SE
 +
enable_se_clkrst();
 +
 +
// Set MISC_CLK_ENB
 +
// This makes fuse registers visible
 +
enable_misc_clk(0x01);
 +
 +
// Setup the security engine's address
 +
set_se_addr(0x70012000);
 +
 +
// Check SE global config
 +
check_se_status();
 +
 +
// Read FUSE_SKU_INFO and compare with 0x83
 +
check_sku();
 +
 +
// Check configuration fuses
 +
check_config_fuses();
 +
 +
u32 bct_iram_addr = 0x40000000;
 +
 +
// Check bootloader version from BCT
 +
check_bootloader_ver(bct_iram_addr);
 +
 +
// Check anti-downgrade fuses
 +
check_downgrade();
 +
 +
// Setup memory controllers
 +
enable_mem_ctl();
 +
 
 +
// Clear SYS_CLK_DIVISOR
 +
*(u32 *)CLK_SOURCE_SYS = 0;
 +
 +
// Place I2C5 in reset
 +
u32 rst_dev_h_val = *(u32 *)RST_DEVICES_H;
 +
rst_dev_h_val &= ~(0x8000);
 +
rst_dev_h_val |= 0x8000;
 +
*(u32 *)RST_DEVICES_H = rst_dev_h_val;
 +
 +
// Program the HOST1X clock and resets
 +
// Uses RST_DEVICES_L, CLK_OUT_ENB_L, CLK_SOURCE_HOST1X and CLK_L_HOST1X
 +
enable_host1x_clkrst();
 +
 +
// Program the TSEC clock and resets
 +
// Uses RST_DEVICES_U, CLK_OUT_ENB_U, CLK_SOURCE_TSEC and CLK_U_TSEC
 +
enable_tsec_clkrst();
 +
 +
// Program the SOR_SAFE clock and resets
 +
// Uses RST_DEVICES_Y, CLK_OUT_ENB_Y and CLK_Y_SOR_SAFE
 +
enable_sor_safe_clkrst();
 +
 +
// Program the SOR0 clock and resets
 +
// Uses RST_DEVICES_X, CLK_OUT_ENB_X and CLK_X_SOR0
 +
enable_sor0_clkrst();
 +
 +
// Program the SOR1 clock and resets
 +
// Uses RST_DEVICES_X, CLK_OUT_ENB_X, CLK_SOURCE_SOR1 and CLK_X_SOR1
 +
enable_sor1_clkrst();
 +
 +
// Program the KFUSE clock resets
 +
// Uses RST_DEVICES_H, CLK_OUT_ENB_H and CLK_H_KFUSE
 +
enable_kfuse_clkrst();
 +
 +
// Clear the Falcon DMA control register
 +
*(u32 *)FALCON_DMACTL = 0;
 +
 +
// Enable Falcon IRQs
 +
*(u32 *)FALCON_IRQMSET = 0xFFF2;
 +
 +
// Enable Falcon IRQs
 +
*(u32 *)FALCON_IRQDEST = 0xFFF0;
 +
 +
// Enable Falcon interfaces
 +
*(u32 *)FALCON_ITFEN = 0x03;
 +
 +
// Wait for Falcon's DMA engine to be idle
 +
wait_flcn_dma_idle();
 +
 +
// Set DMA transfer base address to 0x40010E00>> 0x08
 +
*(u32 *)FALCON_DMATRFBASE = 0x40010E;
 +
 +
u32 trf_mode = 0;    // A value of 0 sets FALCON_DMATRFCMD_IMEM
 +
u32 dst_offset = 0;
 +
u32 src_offset = 0;
 +
 +
// Load code into Falcon (0x100 bytes at a time)
 +
while (src_offset < 0x2900)
 +
{
 +
    flcn_load_firm(trf_mode, src_offset, dst_offset);
 +
    src_offset += 0x100;
 +
    dst_offset += 0x100;
 +
}
 +
 +
// Set magic value in host1x scratch space
 +
*(u32 *)0x50003300 = 0x34C2E1DA;
 +
 +
// Clear Falcon scratch1 MMIO
 +
*(u32 *)FALCON_SCRATCH1 = 0;
 +
 +
// Set Falcon boot key version in scratch0 MMIO
 +
*(u32 *)FALCON_SCRATCH0 = 0x01;
 +
 +
// Set Falcon's boot vector address
 +
*(u32 *)FALCON_BOOTVEC = 0;
 +
 +
// Signal Falcon's CPU
 +
*(u32 *)FALCON_CPUCTL = 0x02;
 +
 +
// Infinite loop
 +
deadlock();
 +
</syntaxhighlight>
 +
 
 +
===== Panic =====
 
If a panic occurs, all sensitive memory contents are cleared, the security engine and fuse programming are disabled and the boot processor is left in a halted state.
 
If a panic occurs, all sensitive memory contents are cleared, the security engine and fuse programming are disabled and the boot processor is left in a halted state.
    +
<syntaxhighlight lang="c">
 
  // Clear all stack contents
 
  // Clear all stack contents
 
  clear_stack();
 
  clear_stack();
Line 129: Line 321:  
  clear_mem();
 
  clear_mem();
 
   
 
   
  // Clear the stage 1 binary
+
  // Clear the PK11 blob from memory
  clear_stage1();
+
  clear_pk11_blob();
  −
u32 FLOW_CTLR_HALT_COP_EVENTS = 0x60007004;
  −
u32 FLOW_MODE_STOP = 0x40000000;
  −
u32 HALT_COP_EVENT_JTAG = 0x10000000;
   
   
 
   
 
  // Halt the boot processor
 
  // Halt the boot processor
 
  while (true)
 
  while (true)
 
     *(u32 *)FLOW_CTLR_HALT_COP_EVENTS = (FLOW_MODE_STOP | HALT_COP_EVENT_JTAG);
 
     *(u32 *)FLOW_CTLR_HALT_COP_EVENTS = (FLOW_MODE_STOP | HALT_COP_EVENT_JTAG);
 +
</syntaxhighlight>
   −
==== Anti-downgrade ====
+
===== Anti-downgrade =====
 
See [[Fuses#Anti-downgrade|Anti-downgrade]].
 
See [[Fuses#Anti-downgrade|Anti-downgrade]].
   −
==== Memory controllers ====
+
===== Memory controllers =====
 
After disabling fuse programming, the bootloader configures the EMC and MEM/MC. It additionally disables QSPI resets and programs a special aperture designed for AHB redirected access to IRAM.
 
After disabling fuse programming, the bootloader configures the EMC and MEM/MC. It additionally disables QSPI resets and programs a special aperture designed for AHB redirected access to IRAM.
   −
u32 PERIPH_CLK_SOURCE_EMC = 0x6000619C;
+
<syntaxhighlight lang="c">
u32 CLK_OUT_ENB_SET_H = 0x60006328;
  −
u32 CLK_OUT_ENB_SET_X = 0x60006284;
  −
u32 RST_DEVICES_SET_H = 0x60006308;
  −
u32 RST_DEVICES_CLR_Y = 0x600062AC;
  −
u32 MC_IRAM_REG_CTRL = 0x70019964;
  −
u32 MC_IRAM_BOM = 0x7001965C;
  −
u32 MC_IRAM_TOM = 0x70019660;
  −
   
  // Initialize EMC's clock source
 
  // Initialize EMC's clock source
 
  u32 emc_clk_src_val = *(u32 *)PERIPH_CLK_SOURCE_EMC;
 
  u32 emc_clk_src_val = *(u32 *)PERIPH_CLK_SOURCE_EMC;
Line 203: Line 384:  
 
 
 
 
  return mc_iram_reg_ctrl_val;
 
  return mc_iram_reg_ctrl_val;
 +
</syntaxhighlight>
 +
 +
[6.2.0+] MC_IRAM_TOM is now set to 0x80000000 to allow TSEC to access IRAM and all MMIO.
   −
==== Key generation ====
+
===== Key generation =====
 
After the security engine is ready and before decrypting the next stage, the bootloader initializes and generates several keys into hardware keyslots.
 
After the security engine is ready and before decrypting the next stage, the bootloader initializes and generates several keys into hardware keyslots.
 
For more details on the Switch's cryptosystem, please see [[Cryptosystem|this page]].
 
For more details on the Switch's cryptosystem, please see [[Cryptosystem|this page]].
   −
===== Selection =====
+
[6.2.0+] The key generation process was moved into an encrypted [[TSEC]] payload.
 +
 
 +
====== Selection ======
 
Depending on [[Fuses#FUSE_RESERVED_ODM4|FUSE_RESERVED_ODM4]] and [[Fuses#FUSE_SPARE_BIT_5|FUSE_SPARE_BIT_5]] different static seeds are selected for key generation.
 
Depending on [[Fuses#FUSE_RESERVED_ODM4|FUSE_RESERVED_ODM4]] and [[Fuses#FUSE_SPARE_BIT_5|FUSE_SPARE_BIT_5]] different static seeds are selected for key generation.
    +
<syntaxhighlight lang="c">
 
  // Initialize keyslots 0x0C and 0x0D as readable
 
  // Initialize keyslots 0x0C and 0x0D as readable
 
  init_keyslot(0x0C, 0x15);
 
  init_keyslot(0x0C, 0x15);
Line 296: Line 483:  
   
 
   
 
  return;
 
  return;
 +
</syntaxhighlight>
   −
===== generate_retail_keys =====
+
====== generate_retail_keys ======
In order to generate retail keys, the bootloader starts by initializing TSEC and grabbing it's [[TSEC#Device_key_generation|device key]]. Using static seeds and the SBK, the keyblob injected into the BCT's [[BCT#customer_data|customer_data]] is validated and decrypted. The resulting keys will then be used to generate the master static key and the master device key.
+
In order to generate retail keys, the bootloader starts by initializing TSEC and grabbing it's [[TSEC#TSEC_key_generation|device key]]. Using static seeds and the SBK, the keyblob injected into the BCT's [[BCT#customer_data|customer_data]] is validated and decrypted. The resulting keys will then be used to generate the master static key and the master device key.
    
See the pseudocode bellow for the detailed process.
 
See the pseudocode bellow for the detailed process.
    +
<syntaxhighlight lang="c">
 
  u32 in_addr = 0;
 
  u32 in_addr = 0;
 
  u32 in_size = 0;
 
  u32 in_size = 0;
Line 359: Line 548:  
  aes_cmac(out_addr, out_size, keyslot, in_addr, in_size);
 
  aes_cmac(out_addr, out_size, keyslot, in_addr, in_size);
 
   
 
   
  // Comapre the generated hash with the first
+
  // Compare the generated hash with the first
 
  // 0x10 bytes of bct_customer_data
 
  // 0x10 bytes of bct_customer_data
 
  bool match = safe_memcmp(mac_addr, bct_customer_data_addr, 0x10);
 
  bool match = safe_memcmp(mac_addr, bct_customer_data_addr, 0x10);
Line 412: Line 601:  
   
 
   
 
  return;
 
  return;
 +
</syntaxhighlight>
   −
===== generate_debug_keys =====
+
====== generate_debug_keys ======
 
In order to generate debug keys, the bootloader only uses static seeds, the SBK and the SSK.
 
In order to generate debug keys, the bootloader only uses static seeds, the SBK and the SSK.
    
See the pseudocode bellow for the detailed process.
 
See the pseudocode bellow for the detailed process.
    +
<syntaxhighlight lang="c">
 
  u32 in_addr = 0;
 
  u32 in_addr = 0;
 
  u32 in_size = 0;
 
  u32 in_size = 0;
Line 478: Line 669:  
   
 
   
 
  return;
 
  return;
 +
</syntaxhighlight>
   −
==== Stage 1 loading ====
+
=== Package1 (PK11) ===
After generating all the necessary keys, the bootloader proceeds to decrypt and launch the next stage.
+
This blob is stored encrypted inside the package and is decrypted by package1ldr.
   −
===== Decryption =====
+
==== Encryption ====
The encrypted stage 1 binary is stored inside the package prepended with it's CTR and total image size. After checking the image's size against an hardcoded value (can change on firmware updates), the image is AES-CTR decrypted and the keyslot used for decryption is immediately cleared.
+
The encrypted blob is prepended with it's CTR and total image size. After checking the image's size against an hardcoded value (can change on firmware updates), the image is AES-CTR decrypted and the keyslot used for decryption is immediately cleared.
   −
  // Maximum stage 1 size on firmware version 1.0.0
+
<syntaxhighlight lang="c">
  u32 max_stage1_size = 0x29000;
+
  // Maximum encrypted blob's size on firmware version 1.0.0
 +
  u32 max_pk11_enc_blob_size = 0x29000;
 
   
 
   
  u32 stage1_image_size = *(u32 *)stage1_addr;
+
  u32 pk11_enc_blob_size = *(u32 *)pk11_blob_addr;
  u32 stage1_image_ctr_addr = stage1_addr + 0x10;  
+
  u32 pk11_enc_blob_ctr_addr = pk11_blob_addr + 0x10;  
  u32 stage1_image_addr = stage1_addr + 0x20;
+
  u32 pk11_enc_blob_addr = pk11_blob_addr + 0x20;
 
   
 
   
  // Validate stage 1's size
+
  // Validate the encrypted blob's size
  if (stage1_image_size > max_stage1_size)
+
  if (pk11_enc_blob_size > max_pk11_enc_blob_size)
 
     panic();
 
     panic();
 
   
 
   
  u32 in_addr = stage1_image_addr;
+
  u32 in_addr = pk11_enc_blob_addr;
  u32 in_size = stage1_image_size;
+
  u32 in_size = pk11_enc_blob_size;
  u32 ctr_addr = stage1_image_ctr_addr;
+
  u32 ctr_addr = pk11_enc_blob_ctr_addr;
 
  u32 ctr_size = 0x10;
 
  u32 ctr_size = 0x10;
  u32 out_addr = stage1_image_addr;
+
  u32 out_addr = pk11_dec_blob_addr;
  u32 out_size = stage1_image_size;
+
  u32 out_size = pk11_dec_blob_size;
 
  u32 keyslot = 0x0B;
 
  u32 keyslot = 0x0B;
 
   
 
   
 
  // AES-CTR decrypt
 
  // AES-CTR decrypt
  // Use the pk11_key (keyslot 0x0B) to decrypt stage 1 in place
+
  // Use the pk11_key (keyslot 0x0B) to decrypt the blob in place
 
  aes_ctr_decrypt(out_addr, out_size, keyslot, in_addr, in_size, ctr_addr, ctr_size);
 
  aes_ctr_decrypt(out_addr, out_size, keyslot, in_addr, in_size, ctr_addr, ctr_size);
 
   
 
   
Line 511: Line 704:  
  clear_keyslot(0x0B);
 
  clear_keyslot(0x0B);
 
   
 
   
  // Validate the decrypted stage 1 image
+
  // Validate the decrypted blob
 
  // Checks the "PK11" magic and some pk11 header fields
 
  // Checks the "PK11" magic and some pk11 header fields
  bool is_valid = check_stage1(stage1_image_addr, stage1_image_size);
+
  bool is_valid = check_pk11_header(pk11_dec_blob_addr, pk11_dec_blob_size);
 
   
 
   
  // Invalid stage 1 image
+
  // Invalid PK11 image
 
  if (!is_valid)
 
  if (!is_valid)
 
     panic();
 
     panic();
 
   
 
   
 
  u32 pk11_header_size = 0x20;
 
  u32 pk11_header_size = 0x20;
  u32 pk11_sec0_offset = *(u32 *)stage1_image_addr + 0x14;
+
  u32 pk11_sec1_offset = *(u32 *)pk11_dec_blob_addr + 0x14;
  u32 pk11_sec1_size = *(u32 *)stage1_image_addr + 0x18;
+
  u32 pk11_sec2_size = *(u32 *)pk11_dec_blob_addr + 0x18;
 
   
 
   
  // Calculate PK11 main entrypoint
+
  // Calculate NX bootloader's entrypoint
  u32 pk11_main_addr = (stage1_image_addr + pk11_header_size + pk11_sec0_offset + pk11_sec1_size);
+
  u32 nx_boot_addr = (pk11_dec_blob_addr + pk11_header_size + pk11_sec1_offset + pk11_sec2_size);
 
 
 
 
  return pk11_main_addr;
+
  return nx_boot_addr;
 +
</syntaxhighlight>
   −
== Stage 1 ==
+
==== Header ====
Known as "package1.1", the code for this stage is stored encrypted inside the package. When decrypted, this stage is encapsulated in a header.
+
When decrypted, the blob is encapsulated in the following header.
   −
=== Header ===
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 544: Line 737:  
| 0x4
 
| 0x4
 
| 4
 
| 4
| Main size
+
| Section 0 size
 
|-
 
|-
 
| 0x8
 
| 0x8
| 8
+
| 4
 +
| Section 0 offset
 +
|-
 +
| 0xC
 +
| 4
 
| Unknown
 
| Unknown
 
|-
 
|-
 
| 0x10
 
| 0x10
 
| 4
 
| 4
| Section 0 size
+
| Section 1 size
 
|-
 
|-
 
| 0x14
 
| 0x14
 
| 4
 
| 4
| Section 0 offset
+
| Section 1 offset
 
|-
 
|-
 
| 0x18
 
| 0x18
 
| 4
 
| 4
| Section 1 size
+
| Section 2 size
 
|-
 
|-
 
| 0x1C
 
| 0x1C
 
| 4
 
| 4
| Section 1 offset
+
| Section 2 offset
 
|}
 
|}
   −
= Changelog =
+
What each section is used for may vary per system-version.
== 3.0.0 ==
+
 
* The functions set_se_addr() and check_se_status() are now called right after enabling the security engine clocks and resets.
+
==== Section 0 ====
See [[Switch_System_Flaws#Stage_1_Bootloader]].
+
This section contains the warmboot binary.
 +
 
 +
==== Section 1 ====
 +
This section contains the NX bootloader, which is run after the initial bootloader in package1.
   −
* Keyslot 0x0A is now used instead of keyslot 0x0D for generating the master_device_key.
+
==== Section 2 ====
 +
This section contains the Secure Monitor binary.
 +
 
 +
== Mariko ==
 +
This package is now distributed in a custom, signed and encrypted format.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x110
 +
| Cryptographic signature
 +
0x0000: CryptoHash (empty)
 +
0x0010: RsaPssSig
 +
|-
 +
| 0x110
 +
| 0x20
 +
| Random block
 +
|-
 +
| 0x130
 +
| 0x20
 +
| SHA256 hash over package1 data
 +
|-
 +
| 0x150
 +
| 0x4
 +
| Version
 +
|-
 +
| 0x154
 +
| 0x4
 +
| Length
 +
|-
 +
| 0x158
 +
| 0x4
 +
| LoadAddress
 +
|-
 +
| 0x15C
 +
| 0x4
 +
| EntryPoint
 +
|-
 +
| 0x160
 +
| 0x10
 +
| Reserved
 +
|-
 +
| 0x170
 +
| Variable
 +
| Package1 data
 +
0x0170: [[Package1#Header|Header]]
 +
0x0190: Body (encrypted)
 +
|}

Navigation menu