Changes

1,814 bytes added ,  19:33, 18 December 2022
describe boot header in more detail
Line 1: Line 1:  
[[Image:boot-stage2-error.jpeg|frame|This may have been a Stage 2 bootloader error.]]
 
[[Image:boot-stage2-error.jpeg|frame|This may have been a Stage 2 bootloader error.]]
   −
Unlike the stage1 bootloader, which must be small enough to fit in ROM (probably several kilobytes), the stage2 bootloader has about a megabyte of NAND flash reserved for it. The stage2 bootloader understands partitions and filesystems, and it is capable of loading the DSi menu. It also must understand the encryption used on filesystem blocks in the NAND, and it must understand how to load and validate title metadata.
+
Unlike the stage1 bootloader, which must be small enough to fit in ROM (32 kilobytes per core), the stage2 bootloader has about a megabyte of NAND flash reserved for it. The stage2 bootloader understands partitions and filesystems, and it is capable of loading the DSi menu. It also must understand the encryption used on filesystem blocks in the NAND, and it must understand how to load and validate title metadata.
   −
The Stage 2 loader was not modified by the [[System Menu 1.4]] update. This is still earlier in the boot process than the "Health and Safety" warning(that warning is displayed by the sysmenu).
+
The Stage 2 loader was not modified by the [[System Menu 1.4]] update. This is still earlier in the boot process than the "Health and Safety" warning (that warning is displayed by the sysmenu).
   −
The first stage bootloader reads the sector at offset 0x200 in order to find a table of offsets to the Stage 2 bootloader:
+
The [[stage1|first stage bootloader]] reads the sector at offset 0x200 in order to find a table of offsets to the Stage 2 bootloader:
    
  00000220  00 08 00 00 10 64 02 00  00 80 7b 03 00 66 02 00  |.....d....{..f..|
 
  00000220  00 08 00 00 10 64 02 00  00 80 7b 03 00 66 02 00  |.....d....{..f..|
Line 29: Line 29:  
| 0x24
 
| 0x24
 
| 0x4
 
| 0x4
| ARM9 Bootcode, Size "Actual binary size"
+
| ARM9 Bootcode, Size "Actual decompressed binary size"
 
|-
 
|-
 
| 0x28
 
| 0x28
Line 37: Line 37:  
| 0x2C
 
| 0x2C
 
| 0x4
 
| 0x4
| ARM9 Bootcode, Size rounded up to multiple of 0x200
+
| ARM9 Bootcode, Size (compressed, if compression is used) rounded up to multiple of 0x200
 
|-
 
|-
 
| 0x30
 
| 0x30
Line 45: Line 45:  
| 0x34
 
| 0x34
 
| 0x4
 
| 0x4
| ARM7 Bootcode, Size "Actual binary size"
+
| ARM7 Bootcode, Size "Actual decompressed binary size"
 
|-
 
|-
 
| 0x38
 
| 0x38
Line 53: Line 53:  
| 0x3C
 
| 0x3C
 
| 0x4
 
| 0x4
| ARM7 Bootcode, Size rounded up to multiple of 0x200
+
| ARM7 Bootcode, Size (compressed, if compression is used) rounded up to multiple of 0x200
 
|-
 
|-
 
| 0x40
 
| 0x40
Line 61: Line 61:  
| 0xFF
 
| 0xFF
 
| 0x1
 
| 0x1
| Unknown, value 0xFF? (actually, this is appears to be always 0Ch, not FFh?)
+
| Option flags (see below). Mostly used for NAND and NVRAM boots, only a single bit is checked for game cartridge boots! Typically 0x0C for NAND boots. NVRAM sets this to 0x80 to signal a NAND boot.
 
|-
 
|-
 
| 0x100
 
| 0x100
Line 88: Line 88:  
|}
 
|}
   −
Note that the above format resembles the [[DSi Cartridge Header]] (entries 0x20-0x3F are roughly similar, and entries 0x180-0x1AF appear to be same as in cart header).
+
Note that the above format roughly resembles the [[DSi Cartridge Header]] (entries 0x20-0x3F are roughly similar, and entries 0x180-0x1AF appear to be same as in cart header).
   −
The RSA pubks(the one for 3DS and the other one for DSi) for the below signature can be obtained from 3DS TWL_FIRM Process9(this is required for getting the binaries' keyY). It's unknown(?) if the DSi bootrom(s) copy this modulo to anywhere outside of bootrom.
+
The option byte at +0xff has the following flags:
 +
{| border="1" cellpadding="3" cellspacing="0"
 +
! Bit
 +
! Mask
 +
! Description
 +
|-
 +
| 0
 +
| 0x01
 +
| Use LZ77 decompression for the ARM9 binary (game cartridge boots ignore this flag and always treat binaries as uncompressed)
 +
|-
 +
| 1
 +
| 0x02
 +
| Use LZ77 decompression for the ARM7 binary (game cartridge boots ignore this flag and always treat binaries as uncompressed)
 +
|-
 +
| 2
 +
| 0x04
 +
| Run the ARM9 at 133 MHz when performing RSA verification and SHA1 hash calculation (it starts out at 66 MHz). This is the only flag checked during a game cartridge boot.
 +
|-
 +
| 3
 +
| 0x08
 +
| Use the IPC FIFO to send compressed payloads to the ARM9, and have the ARM9 decompress them. If not selected, the ARM7 will decompress the payload, then map it to the ARM9 using the MBK registers. Has no effect for uncompressed payloads (and thus game cartridge boots).
 +
|-
 +
| 4
 +
| 0x10
 +
| Unknown, doesn't seem to be used. Always 0.
 +
|-
 +
| 5
 +
| 0x20
 +
| Unknown, doesn't seem to be used. Always 0.
 +
|-
 +
| 6
 +
| 0x40
 +
| When booting from NWRAM, use an 8 MHz SPI clock. If 0, use a 4 MHz SPI clock. Not used for non-NVRAM boots.
 +
|-
 +
| 7
 +
| 0x80
 +
| Boot medium selection flag: if 1, boot from NAND. If 0, boot from NVRAM. Not applicable for game cartridge boots (which use a magic key combination).
 +
|}
 +
 
 +
The RSA public keys (the one for 3DS and the other one for DSi) for the below signature can be obtained from 3DS TWL_FIRM Process9 (this is required for getting the binaries' keyY). It is also found in the DSi's ARM9 boot ROM, but this is never copied to some place outside the boot ROM. (The bootroms copy _some_ keys to WRAM/ITCM, but not this one.)
    
Structure of the 0x74-byte "hash-data" stored in the RSA message:
 
Structure of the 0x74-byte "hash-data" stored in the RSA message:
Line 104: Line 143:  
| 0x10
 
| 0x10
 
| 0x14
 
| 0x14
| SHA1 hash. Going by 3DS TWL_FIRM this seems to calculated over the first 0x28-bytes of [[NAND]], then the first 0x100-bytes of the header, then the last 0x80-bytes of the header(following the signature). This works with the bootloader contained in TWL_FIRM, however it's unknown how the first part is handled on DSi.
+
| SHA1 hash, calculated over the first 0x28-bytes of [[NAND]], then the first 0x100-bytes of the header, then the last 0x80-bytes of the header (following the signature). This works with both the bootloader contained in TWL_FIRM, and the real DSi ARM9 boot ROM.
 
|-
 
|-
 
| 0x24
 
| 0x24
Line 116: Line 155:  
| 0x4C
 
| 0x4C
 
| 0x14
 
| 0x14
| Unknown, not used by 3DS TWL_FIRM. Normally all-zero.
+
| Unknown, not used by 3DS TWL_FIRM nor DSi bootrom. Normally all-zero.
 
|-
 
|-
 
| 0x60
 
| 0x60
 
| 0x14
 
| 0x14
| Unknown, not used by 3DS TWL_FIRM.
+
| SHA1 of all previous fields in the RSA messasge, used to prevent RSA signature forgery. Not used by 3DS TWL_FIRM(?).
 
|}
 
|}
    
Note that this sector (and two similar ones at 0x400 and 0x600) appear to be the only unencrypted blocks on the NAND flash.
 
Note that this sector (and two similar ones at 0x400 and 0x600) appear to be the only unencrypted blocks on the NAND flash.
   −
After loading+verifying the the above header, the ARM7 binary is loaded+verified, then the ARM9 binary is loaded+verified.
+
After loading+verifying the the above header, the ARM7 binary is loaded+verified, then the ARM9 binary is loaded+verified (see [[stage1]]).
    
Whereas the filesystem data in NAND is encrypted using a unique key for every DSi, the stage2 bootloader is identical on every DSi tested so far. The stage2 bootloader binaries are not encrypted with any console-unique keys.
 
Whereas the filesystem data in NAND is encrypted using a unique key for every DSi, the stage2 bootloader is identical on every DSi tested so far. The stage2 bootloader binaries are not encrypted with any console-unique keys.
Line 137: Line 176:  
   ctr[1] = (unsigned int)(-binblk->binblocksize);
 
   ctr[1] = (unsigned int)(-binblk->binblocksize);
 
   ctr[2] = ~binblk->binblocksize;
 
   ctr[2] = ~binblk->binblocksize;
 +
  ctr[3] = AES block offset (starts at 0)
    
=== Stage2 operations ===
 
=== Stage2 operations ===
 +
 
After Stage 2 is loaded:
 
After Stage 2 is loaded:
 +
# Main RAM (aka FCRAM aka DRAM) is allowed bus access (using the EXMEMCNT MMIO register) and initialized.
 
# The NAND flash is partially re-initialized
 
# The NAND flash is partially re-initialized
# Sector 0 is read from the NAND. This appears to be an (encrypted) DOS-style MBR.
+
# Sector 0 is read from the NAND. This is an (encrypted) DOS-style MBR.
 
# The MBR signature and the type of the first partition are verified.
 
# The MBR signature and the type of the first partition are verified.
 
# Filesystem metadata is read from sectors starting around 0x100000. The metadata is in FAT16 format with long filenames.
 
# Filesystem metadata is read from sectors starting around 0x100000. The metadata is in FAT16 format with long filenames.
75

edits