Difference between revisions of "Stage1"

From DSiBrew
Jump to navigation Jump to search
m (Hallowizer moved page Boot0 to Stage1: commonly used name)
Line 1: Line 1:
 
[[Image:boot-stage1-error.jpeg|frame|When the Stage 1 bootloader (in ROM) fails, it displays a 32-bit hexadecimal number on the top screen.]]
 
[[Image:boot-stage1-error.jpeg|frame|When the Stage 1 bootloader (in ROM) fails, it displays a 32-bit hexadecimal number on the top screen.]]
  
The first stage of the DSi's bootloader lives in ROM, presumably on the CPU die. It loads further encrypted+signed stages from [[NAND]] flash, starting with a plaintext offset table in the sector at offset 0x200.
+
The first stage of the DSi's bootloader lives in ROM, on the CPU-TWL SoC die. It loads further encrypted+signed stages from the selected boot medium (usually [[NAND]] flash), starting with a plaintext offset table in the sector at offset 0x200. The code of the ROMs live at the upper 32k of the BIOS memory areas, i.e. at 0xffff8000 for the ARM9, and 0x00008000 for the ARM7.
  
Not much is known about this bootloader yet, but it presumably knows how to:
+
The bootroms perform the following steps to load, verify and decrypt the [[Stage2|second-stage bootloader]]:
# Initialize the encryption hardware
+
# Perform some initialization, such as clearing and setting up the .data and .bss sections, setting up the MPU and an RSA heap (ARM9), and the AES hardware (ARM7).
# Read the contents of [[NVRAM]]
+
## At this moment, main RAM (aka FCRAM aka DRAM) isn't initialized yet, and is unusable. It is only initialized at the very beginning of [[stage2]].
# Initialize both LCDs
+
## The ARM9 initializes its DTCM to reside at 0x02ff8000, an area normally backed by DRAM that also contains the exception vectors. DTCM is marked as no-execute, and the NWRAM area is marked as cacheable. ITCM is r/w/x.
# Read blocks (but not files) from the [[NAND]] flash
+
# Read configuration bytes from [[NVRAM]]: the first 0x28 bytes and the single byte at 0x2ff are loaded.
# Perform some variety of integrity check on all data it reads (signature, CRC, ?)
+
# Decide on the boot medium:
# Display basic hexadecimal error codes
+
## If the magic key combination "X+start+select+lid down" is held down and a game cartridge is inserted, booting from it is attempted (much like the 3DS boot ROMs). Note that the contents of the game cartridge must adhere to the regular [[stage2]] header format, so booting from retail game cartridges won't work.
# Possibly factory-programming the [[NAND]] flash?
+
## If the most significant bit of the byte at 0x2ff of NVRAM is high, NAND will be used as a boot medium.
# Might also do basic power-on self test of peripherals
+
## As a fallback, the console will try to boot from NVRAM. (On retail consoles, this always fails as NVRAM does not contain any bootcode.)
 +
## If one boot method fails, the bootroms will continue trying with the next one.
 +
# 0x200 bytes at offset 0x200 from the boot medium are read. This contains the [[Stage2|stage2 header]].
 +
# The RSA signature of the stage2 header is verified, and the first two SHA1 hashes (of the rest of the stage2 header, and the hash of the RSA message itself) are verified.
 +
# On failure, goto 10.
 +
# On success, the ARM9 instructs the ARM7 to load and decrypt the stage2 ARM7 binary from the boot medium. DMA is used from the boot medium to the AES hardware, but the outupt of the AES accelerator is simply read by software.
 +
## Depending on the option bits in the stage2 header, this payload may be compressed.
 +
## Uncompressed payloads are loaded into NWRAM on the ARM7 side, and then mapped to the ARM9 using the MBK registers.
 +
## For compressed payloads, either the above can happen too, or the compressed data can first be sent to the ARM9 using the IPC FIFO, where the latter then performs the decompression.
 +
## After the loading happens, the SHA1 hash is checked, but the result is not yet communicated.
 +
# The above is repeated for the stage2 ARM9 binary.
 +
# Only once both binaries have been checked will the ARM9 communicate the hash comparison result to the ARM7.
 +
# On failure, both cores will lock up, and the ARM9 will display an error code on the top screen (see below).
 +
# On success, both cores will:
 +
## Deinitialize some hardware (partially clear RAM, deinitialize the MPU, etc.)
 +
## Prepare keys for the next bootstage (some in the AES hardware, others copied to WRAM or ITCM)
 +
## The ARM7 will lock out both boot ROMs from the system memory bus using the SCFG registers. The ARM9 waits for this lockout to happen.
 +
## Both cores, now synchronized using the lockout, will now jump to [[stage2]] code. (Current stage2 binaries will immediately re-synchronize the cores, however.
  
Known error codes:
+
Error codes are supposed to be interpreted as a 32-bit unsigned little-endian integer, the least significant byte describing the status of the NVRAM boot attempt, the next of the NAND boot attempt, and the third one describes the game cartridge boot attempt. The most significant byte is always 0.
 +
 
 +
The individual bytes carry the following meaning:
 +
* 00: The boot method has not been attempted, or failed during physical initialization (eg. NAND clk shorted, or no cartridge was inserted when attempting a game cartridge boot).
 +
* FE: stage2 header verification failed.
 +
* FD: stage2 ARM7 binary verification failed.
 +
* FC: stage3 ARM9 binary verification failed.
 +
The boot ROM does not use any other error codes.
 +
 
 +
In practice, the error codes carry the following meanings:
  
 
{| border="1" cellpadding="3" cellspacing="0"
 
{| border="1" cellpadding="3" cellspacing="0"
 
! Error Code  !!  Description
 
! Error Code  !!  Description
 
|-
 
|-
| 0000FE00 || Error communicating with NAND chip. (It's missing, CLK is shorted, etc.)
+
| 0000FE00 || Error communicating with NAND chip (it's missing, CLK is shorted, etc.), or the most significant bit of the byte at 0x2ff of [NVRAM] has been cleared.
 
|-
 
|-
| 0000FEFC || Integrity error in first block of Stage 2 (address at 0x220)
+
| 0000FEFC || Integrity error in ARM9 info block of Stage 2 (address at 0x220)
 
|-
 
|-
| 0000FEFD || Integrity error in second block of Stage 2 (address at 0x230)
+
| 0000FEFD || Integrity error in ARM7 info block of Stage 2 (address at 0x230)
 
|-
 
|-
| 0000FEFE || Boot sector integrity error (Sector 0x200 not valid), or error in [[NVRAM]] contents.
+
| 0000FEFE || Integrity error in the stage2 header (or error in [[NVRAM]] contents).
 
|}
 
|}

Revision as of 19:10, 18 December 2022

When the Stage 1 bootloader (in ROM) fails, it displays a 32-bit hexadecimal number on the top screen.

The first stage of the DSi's bootloader lives in ROM, on the CPU-TWL SoC die. It loads further encrypted+signed stages from the selected boot medium (usually NAND flash), starting with a plaintext offset table in the sector at offset 0x200. The code of the ROMs live at the upper 32k of the BIOS memory areas, i.e. at 0xffff8000 for the ARM9, and 0x00008000 for the ARM7.

The bootroms perform the following steps to load, verify and decrypt the second-stage bootloader:

  1. Perform some initialization, such as clearing and setting up the .data and .bss sections, setting up the MPU and an RSA heap (ARM9), and the AES hardware (ARM7).
    1. At this moment, main RAM (aka FCRAM aka DRAM) isn't initialized yet, and is unusable. It is only initialized at the very beginning of stage2.
    2. The ARM9 initializes its DTCM to reside at 0x02ff8000, an area normally backed by DRAM that also contains the exception vectors. DTCM is marked as no-execute, and the NWRAM area is marked as cacheable. ITCM is r/w/x.
  2. Read configuration bytes from NVRAM: the first 0x28 bytes and the single byte at 0x2ff are loaded.
  3. Decide on the boot medium:
    1. If the magic key combination "X+start+select+lid down" is held down and a game cartridge is inserted, booting from it is attempted (much like the 3DS boot ROMs). Note that the contents of the game cartridge must adhere to the regular stage2 header format, so booting from retail game cartridges won't work.
    2. If the most significant bit of the byte at 0x2ff of NVRAM is high, NAND will be used as a boot medium.
    3. As a fallback, the console will try to boot from NVRAM. (On retail consoles, this always fails as NVRAM does not contain any bootcode.)
    4. If one boot method fails, the bootroms will continue trying with the next one.
  4. 0x200 bytes at offset 0x200 from the boot medium are read. This contains the stage2 header.
  5. The RSA signature of the stage2 header is verified, and the first two SHA1 hashes (of the rest of the stage2 header, and the hash of the RSA message itself) are verified.
  6. On failure, goto 10.
  7. On success, the ARM9 instructs the ARM7 to load and decrypt the stage2 ARM7 binary from the boot medium. DMA is used from the boot medium to the AES hardware, but the outupt of the AES accelerator is simply read by software.
    1. Depending on the option bits in the stage2 header, this payload may be compressed.
    2. Uncompressed payloads are loaded into NWRAM on the ARM7 side, and then mapped to the ARM9 using the MBK registers.
    3. For compressed payloads, either the above can happen too, or the compressed data can first be sent to the ARM9 using the IPC FIFO, where the latter then performs the decompression.
    4. After the loading happens, the SHA1 hash is checked, but the result is not yet communicated.
  8. The above is repeated for the stage2 ARM9 binary.
  9. Only once both binaries have been checked will the ARM9 communicate the hash comparison result to the ARM7.
  10. On failure, both cores will lock up, and the ARM9 will display an error code on the top screen (see below).
  11. On success, both cores will:
    1. Deinitialize some hardware (partially clear RAM, deinitialize the MPU, etc.)
    2. Prepare keys for the next bootstage (some in the AES hardware, others copied to WRAM or ITCM)
    3. The ARM7 will lock out both boot ROMs from the system memory bus using the SCFG registers. The ARM9 waits for this lockout to happen.
    4. Both cores, now synchronized using the lockout, will now jump to stage2 code. (Current stage2 binaries will immediately re-synchronize the cores, however.

Error codes are supposed to be interpreted as a 32-bit unsigned little-endian integer, the least significant byte describing the status of the NVRAM boot attempt, the next of the NAND boot attempt, and the third one describes the game cartridge boot attempt. The most significant byte is always 0.

The individual bytes carry the following meaning:

  • 00: The boot method has not been attempted, or failed during physical initialization (eg. NAND clk shorted, or no cartridge was inserted when attempting a game cartridge boot).
  • FE: stage2 header verification failed.
  • FD: stage2 ARM7 binary verification failed.
  • FC: stage3 ARM9 binary verification failed.

The boot ROM does not use any other error codes.

In practice, the error codes carry the following meanings:

Error Code Description
0000FE00 Error communicating with NAND chip (it's missing, CLK is shorted, etc.), or the most significant bit of the byte at 0x2ff of [NVRAM] has been cleared.
0000FEFC Integrity error in ARM9 info block of Stage 2 (address at 0x220)
0000FEFD Integrity error in ARM7 info block of Stage 2 (address at 0x230)
0000FEFE Integrity error in the stage2 header (or error in NVRAM contents).