Line 12: |
Line 12: |
| 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 21: |
| // 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 112: |
Line 115: |
| | | |
| return; | | return; |
| + | </syntaxhighlight> |
| | | |
| ==== Panic ==== | | ==== 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 139: |
Line 144: |
| 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 ==== |
Line 146: |
Line 152: |
| 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. |
| | | |
| + | <syntaxhighlight lang="c"> |
| u32 PERIPH_CLK_SOURCE_EMC = 0x6000619C; | | u32 PERIPH_CLK_SOURCE_EMC = 0x6000619C; |
| u32 CLK_OUT_ENB_SET_H = 0x60006328; | | u32 CLK_OUT_ENB_SET_H = 0x60006328; |
Line 203: |
Line 210: |
| | | |
| return mc_iram_reg_ctrl_val; | | return mc_iram_reg_ctrl_val; |
| + | </syntaxhighlight> |
| | | |
| ==== Key generation ==== | | ==== Key generation ==== |
Line 211: |
Line 219: |
| 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 305: |
| | | |
| return; | | return; |
| + | </syntaxhighlight> |
| | | |
| ===== generate_retail_keys ===== | | ===== generate_retail_keys ===== |
Line 302: |
Line 312: |
| 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 412: |
Line 423: |
| | | |
| return; | | return; |
| + | </syntaxhighlight> |
| | | |
| ===== generate_debug_keys ===== | | ===== generate_debug_keys ===== |
Line 418: |
Line 430: |
| 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 491: |
| | | |
| return; | | return; |
| + | </syntaxhighlight> |
| | | |
| == PK11 Blob == | | == PK11 Blob == |
Line 485: |
Line 499: |
| 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. | | 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. |
| | | |
| + | <syntaxhighlight lang="c"> |
| // Maximum encrypted blob's size on firmware version 1.0.0 | | // Maximum encrypted blob's size on firmware version 1.0.0 |
| u32 max_pk11_enc_blob_size = 0x29000; | | u32 max_pk11_enc_blob_size = 0x29000; |
Line 527: |
Line 542: |
| | | |
| return nx_boot_addr; | | return nx_boot_addr; |
| + | </syntaxhighlight> |
| | | |
| === Header === | | === Header === |