Changes

5,298 bytes added ,  22:02, 5 November 2019
no edit summary
Line 1: Line 1:  
The Nintendo Switch makes use of Tegra's fuse driver for a number of operations. This driver is mapped to physical address 0x7000F800 with a total size of 0x400 bytes and exposes several registers for fuse programming.
 
The Nintendo Switch makes use of Tegra's fuse driver for a number of operations. This driver is mapped to physical address 0x7000F800 with a total size of 0x400 bytes and exposes several registers for fuse programming.
   −
Registers from 0x7000F800 to 0x7000F800 + 0xFF can be used to directly program the hardware fuse array, while registers from 0x7000F800 + 0x100 (FUSE_CHIP_REG_START_OFFSET) to 0x7000F800 + 0x3FC (FUSE_CHIP_REG_END_OFFSET) represent cached values read from certain fuses.
+
Registers from 0x7000F800 to 0x7000F800 + 0xFF can be used to directly program the hardware fuse bitmap, while registers from 0x7000F800 + 0x100 (FUSE_CHIP_REG_START_OFFSET) to 0x7000F800 + 0x3FC (FUSE_CHIP_REG_END_OFFSET) represent cached values read from certain fuses.
    
== Registers ==
 
== Registers ==
Line 11: Line 11:  
!  Address
 
!  Address
 
|-
 
|-
| [[#FUSE_CTRL|FUSE_CTRL]]
+
| [[#FUSE_FUSECTRL|FUSE_FUSECTRL]]
 
| 0x7000F800
 
| 0x7000F800
 
|-
 
|-
| [[#FUSE_REG_ADDR|FUSE_REG_ADDR]]
+
| [[#FUSE_FUSEADDR|FUSE_FUSEADDR]]
 
| 0x7000F804
 
| 0x7000F804
 
|-
 
|-
| [[#FUSE_REG_READ|FUSE_REG_READ]]
+
| [[#FUSE_FUSERDATA|FUSE_FUSERDATA]]
 
| 0x7000F808
 
| 0x7000F808
 
|-
 
|-
| [[#FUSE_REG_WRITE|FUSE_REG_WRITE]]
+
| [[#FUSE_FUSEWDATA|FUSE_FUSEWDATA]]
 
| 0x7000F80C
 
| 0x7000F80C
 
|-
 
|-
| FUSE_TIME_RD1
+
| FUSE_FUSETIME_RD1
 
| 0x7000F810
 
| 0x7000F810
 
|-
 
|-
| FUSE_TIME_RD2
+
| FUSE_FUSETIME_RD2
 
| 0x7000F814
 
| 0x7000F814
 
|-
 
|-
| FUSE_TIME_PGM1
+
| FUSE_FUSETIME_PGM1
 
| 0x7000F818
 
| 0x7000F818
 
|-
 
|-
| [[#FUSE_TIME_PGM2|FUSE_TIME_PGM2]]
+
| [[#FUSE_FUSETIME_PGM2|FUSE_FUSETIME_PGM2]]
 
| 0x7000F81C
 
| 0x7000F81C
 
|-
 
|-
| [[#FUSE_PRIV2INTFC|FUSE_PRIV2INTFC]]
+
| [[#FUSE_PRIV2INTFC_START|FUSE_PRIV2INTFC_START]]
 
| 0x7000F820
 
| 0x7000F820
 
|-
 
|-
Line 44: Line 44:  
| 0x7000F828
 
| 0x7000F828
 
|-
 
|-
| [[#FUSE_DIS_PGM|FUSE_DIS_PGM]]
+
| [[#FUSE_DISABLEREGPROGRAM|FUSE_DISABLEREGPROGRAM]]
 
| 0x7000F82C
 
| 0x7000F82C
 
|-
 
|-
| [[#FUSE_WRITE_ACCESS|FUSE_WRITE_ACCESS]]
+
| [[#FUSE_WRITE_ACCESS_SW|FUSE_WRITE_ACCESS_SW]]
 
| 0x7000F830
 
| 0x7000F830
 
|-
 
|-
Line 56: Line 56:  
| 0x7000F83C
 
| 0x7000F83C
 
|-
 
|-
| FUSE_TIME_RD3
+
| FUSE_FUSETIME_RD3
 
| 0x7000F84C
 
| 0x7000F84C
 
|-
 
|-
Line 75: Line 75:  
|}
 
|}
   −
==== FUSE_CTRL ====
+
==== FUSE_FUSECTRL ====
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Bits
 
!  Bits
Line 81: Line 81:  
|-
 
|-
 
| 0-1
 
| 0-1
| Fuse command (1 = FUSE_READ; 2 = FUSE_WRITE; 3 = FUSE_SENSE)
+
| FUSE_FUSECTRL_CMD
 +
0x00: IDLE
 +
0x01: READ
 +
0x02: WRITE
 +
0x03: SENSE_CTRL
 
|-
 
|-
 
| 16-20
 
| 16-20
| Fuse state (4 = STATE_IDLE)
+
| FUSE_FUSECTRL_STATE
 +
0x00: STATE_RESET
 +
0x01: STATE_POST_RESET
 +
0x02: STATE_LOAD_ROW0
 +
0x03: STATE_LOAD_ROW1
 +
0x04: STATE_IDLE
 +
0x05: STATE_READ_SETUP
 +
0x06: STATE_READ_STROBE
 +
0x07: STATE_SAMPLE_FUSES
 +
0x08: STATE_READ_HOLD
 +
0x09: STATE_FUSE_SRC_SETUP
 +
0x0A: STATE_WRITE_SETUP
 +
0x0B: STATE_WRITE_ADDR_SETUP
 +
0x0C: STATE_WRITE_PROGRAM
 +
0x0D: STATE_WRITE_ADDR_HOLD
 +
0x0E: STATE_FUSE_SRC_HOLD
 +
0x0F: STATE_LOAD_RIR
 +
0x10: STATE_READ_BEFORE_WRITE_SETUP
 +
0x11: STATE_READ_DEASSERT_PD
 +
|-
 +
| 21
 +
| FUSE_FUSECTRL_MARGIN_READ
 +
|-
 +
| 22
 +
| FUSE_FUSECTRL_RWL
 +
|-
 +
| 23
 +
| FUSE_FUSECTRL_TRCS
 +
|-
 +
| 24
 +
| FUSE_FUSECTRL_AT1
 +
|-
 +
| 25
 +
| FUSE_FUSECTRL_AT0
 
|-
 
|-
 
| 26
 
| 26
| Fuse power down mode flag (FUSE_CTRL_PD)
+
| FUSE_FUSECTRL_PD_CTRL
 
|-
 
|-
 
| 30
 
| 30
| Fuse sense status (FUSE_CTRL_SENSE_DONE)
+
| FUSE_FUSECTRL_FUSE_SENSE_DONE
 +
|-
 +
| 31
 +
| FUSE_FUSECTRL_RECORD_SHIFT_DONE
 
|}
 
|}
    
Before fuse reading/writing the power down mode must be disabled.
 
Before fuse reading/writing the power down mode must be disabled.
FUSE_SENSE mode flushes programmed values into the [[Fuses#Cache_registers|cache registers]].
+
SENSE_CTRL mode flushes programmed values into the [[Fuses#Cache_registers|cache registers]].
   −
==== FUSE_REG_ADDR ====
+
==== FUSE_FUSEADDR ====
 
This register takes the address of the fuse to be read/written/sensed.
 
This register takes the address of the fuse to be read/written/sensed.
   −
==== FUSE_REG_READ ====
+
==== FUSE_FUSERDATA ====
 
This register receives the value read from the fuse.
 
This register receives the value read from the fuse.
   −
==== FUSE_REG_WRITE ====
+
==== FUSE_FUSEWDATA ====
 
This register takes the value to be written to the fuse.
 
This register takes the value to be written to the fuse.
   −
==== FUSE_TIME_PGM2 ====
+
==== FUSE_FUSETIME_PGM2 ====
 
This register takes the fuse programming pulse (0xC0 == 19200 kHz).
 
This register takes the fuse programming pulse (0xC0 == 19200 kHz).
   −
==== FUSE_PRIV2INTFC ====
+
==== FUSE_PRIV2INTFC_START ====
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Bits
 
!  Bits
Line 114: Line 154:  
|-
 
|-
 
| 0
 
| 0
| FUSE_PRIV2INTFC_SDATA
+
| FUSE_PRIV2INTFC_START_DATA
 
|-
 
|-
 
| 1
 
| 1
| FUSE_PRIV2INTFC_SKIP_RECORDS
+
| FUSE_PRIV2INTFC_START_SKIP_RECORDS
 
|}
 
|}
   −
==== FUSE_DIS_PGM ====
+
==== FUSE_DISABLEREGPROGRAM ====
 
If set to 0x01, this register disables fuse programming.
 
If set to 0x01, this register disables fuse programming.
   −
==== FUSE_WRITE_ACCESS ====
+
==== FUSE_WRITE_ACCESS_SW ====
 
If set to 0x01, this register disables software writes to the fuse driver registers.
 
If set to 0x01, this register disables software writes to the fuse driver registers.
   Line 648: Line 688:  
Stores the FT (Final Test) revision.
 
Stores the FT (Final Test) revision.
   −
Original launch units have this value set to 0xA0 (revision 5.0). The first batch of patched units have this value set to 0xC0 (revision 6.0).
+
Original launch units have this value set to 0xA0 (revision 5.0). The first batch of patched units have this value set to 0xC0 (revision 6.0). The second batch of patched units have this value set to 0xE0 (revision 7.0)
    
==== FUSE_FA ====
 
==== FUSE_FA ====
Line 682: Line 722:  
|-
 
|-
 
| 0-1
 
| 0-1
| Unit type (3 = debug; 0 = retail)
+
| Unit type (0x00 = Retail, 0x03 = Debug)
 
|-
 
|-
 
| 2
 
| 2
| Unknown config (must be 1 on retail)
+
| Production flag (0x00 = Prototype, 0x01 = Production)
 
|-
 
|-
 
| [1.0.0-3.0.2] 3-5
 
| [1.0.0-3.0.2] 3-5
Line 692: Line 732:  
|-
 
|-
 
| 8
 
| 8
| Unknown config mask (must be 0 on retail)
+
| Development flag (0x00 = Retail, 0x01 = Development)
 
|-
 
|-
 
| 9
 
| 9
| Unit type mask (0 = debug; 1 = retail)
+
| Unit type flag (0x00 = Debug, 0x01 = Retail)
 
|-
 
|-
 
| 10
 
| 10
| [3.0.0+] Kiosk mode (0 = retail; 1 = kiosk)
+
| [3.0.0+] Kiosk flag (0x00 = Retail, 0x01 = Kiosk/Quest)
 
|-
 
|-
 
| 11
 
| 11
| [5.0.0+] Unit patch flag (0 = unpatched; 1 = patched)
+
| [5.0.0+] Patch flag (0x00 = Unpatched, 1 = Patched)
 
|-
 
|-
 
| 16-19
 
| 16-19
| [4.0.0+] New unit type
+
| [4.0.0+] New hardware type (0x00 = Icosa, 0x01 = Iowa, 0x02 = Hoag)
 
|}
 
|}
   Line 710: Line 750:     
==== FUSE_RESERVED_ODM6 ====
 
==== FUSE_RESERVED_ODM6 ====
This register returns the value programmed into index 0x3A of the fuse array.  
+
This register returns the value programmed into fuse [[#reserved_odm6|reserved_odm6]].
    
==== FUSE_RESERVED_ODM7 ====
 
==== FUSE_RESERVED_ODM7 ====
This register returns the value programmed into index 0x3C of the fuse array.
+
This register returns the value programmed into fuse [[#reserved_odm7|reserved_odm7]].
    
==== FUSE_PUBLIC_KEY ====
 
==== FUSE_PUBLIC_KEY ====
Line 721: Line 761:  
Stores the CP (Chip Probing) revision.
 
Stores the CP (Chip Probing) revision.
   −
Original launch units have this value set to 0xA0 (revision 5.0). The first batch of patched units have this value set to 0x103 (revision 8.3).
+
Original launch units have this value set to 0xA0 (revision 5.0). Patched units have this value set to 0x103 (revision 8.3).
    
==== FUSE_PRIVATE_KEY ====
 
==== FUSE_PRIVATE_KEY ====
Line 751: Line 791:  
|}
 
|}
   −
This caches the value of the sw_reserved fuse from the hardware array.
+
This caches the value of the reserved_sw fuse from the hardware bitmap.
    
Original launch units have the RCM USB controller mode set to USB 2.0, while the first batch of patched units have the RCM USB controller mode set to XUSB.
 
Original launch units have the RCM USB controller mode set to USB 2.0, while the first batch of patched units have the RCM USB controller mode set to XUSB.
    
==== FUSE_PKC_DISABLE ====
 
==== FUSE_PKC_DISABLE ====
This caches the value of the pkc_disable fuse from the hardware array.
+
This caches the value of the pkc_disable fuse from the hardware bitmap.
    
==== FUSE_SPARE_BIT_2 ====
 
==== FUSE_SPARE_BIT_2 ====
Line 769: Line 809:  
==== FUSE_SPARE_BIT_5 ====
 
==== FUSE_SPARE_BIT_5 ====
 
Must be non-zero on retail units, otherwise the first bootloader panics.
 
Must be non-zero on retail units, otherwise the first bootloader panics.
On debug units it can be zero, which tells the bootloader to choose from two debug master key seeds. If set to non-zero on a debug unit, it tells the bootloader to choose from two master key seeds (with the second one being the retail master key seed).
+
On prototype units it can be zero, which tells the bootloader to choose from two pre-production master key seeds. If set to non-zero on a prototype unit, it tells the bootloader to choose from two master key seeds (with the second one being the same as the retail master key seed).
    
[4.0.0+] This value is no longer used during boot.
 
[4.0.0+] This value is no longer used during boot.
   −
== eFuses ==
+
== Bitmap ==
The actual hardware fuses can be programmed through the fuse driver after enabling fuse programming.
+
The actual hardware fuses are stored in a bitmap and may be programmed through the fuse driver after enabling fuse programming.
 +
 
 +
Fuse numbers are relative to the start of the fuse bitmap where each element is a 4 byte word and has a redundant alias. A single fuse write operation must always write the same value to '''fuse_bitmap + ((fuse_number + 0) << 2)''' (PRIMARY_ALIAS) and '''fuse_bitmap + ((fuse_number + 1) << 2)''' (REDUNDANT_ALIAS). However, after offset 0x180 in the fuse bitmap, fuses no longer have a redundant alias.
   −
Below is a list of common fuse indexes used by Tegra devices (and applicable to the Switch).
+
Below is a list of common fuses used by Tegra devices (and applicable to the Switch).
Note that the indexes are relative to the start of the fuse array and each element is a 4 byte word. A single fuse write operation always writes the same word at both fuse_array + 0 (PRIMARY_ALIAS) and fuse_array + 1 (REDUNDANT_ALIAS).
      
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Name
 
!  Name
Index
+
Number
 +
!  Redundant number
 
!  Bits
 
!  Bits
 
|-
 
|-
| jtag_disable
+
| enable_fuse_program
| 0x00
+
| 0
 +
| 1
 +
| 0
 +
|-
 +
| disable_fuse_program
 +
| 0
 +
| 1
 +
| 1
 +
|-
 +
| bypass_fuses
 +
| 0
 +
| 1
 +
| 2
 +
|-
 +
| jtag_direct_access_disable
 +
| 0
 
| 1
 
| 1
 +
| 3
 
|-
 
|-
| odm_production_mode
+
| production_mode
| 0x00
+
| 0
 
| 1
 
| 1
 +
| 4
 +
|-
 +
| jtag_secureid_valid
 +
| 0
 +
| 1
 +
| 5
 
|-
 
|-
 
| odm_lock
 
| odm_lock
| 0x00
+
| 0
| 4
+
| 1
 +
| 6-9
 +
|-
 +
| fa_mode
 +
| 0
 +
| 1
 +
| 10
 +
|-
 +
| security_mode
 +
| 0
 +
| 1
 +
| 11
 +
|-
 +
| arm_debug_dis
 +
| 0
 +
| 1
 +
| 12
 +
|-
 +
| obs_dis
 +
| 0
 +
| 1
 +
| 13
 +
|-
 +
| public_key0
 +
| 10
 +
| 11
 +
| 30-31
 +
|-
 +
| public_key0
 +
| 12
 +
| 13
 +
| 0-29
 +
|-
 +
| public_key1
 +
| 12
 +
| 13
 +
| 30-31
 
|-
 
|-
| public_key
+
| public_key1
| 0x0C
+
| 14
| 256
+
| 15
 +
| 0-29
 
|-
 
|-
| secure_boot_key
+
| public_key2
| 0x22
+
| 14
| 128
+
| 15
 +
| 30-31
 
|-
 
|-
| device_key
+
| public_key2
| 0x2A
+
| 16
| 32
+
| 17
 +
| 0-29
 
|-
 
|-
| sec_boot_dev_cfg
+
| public_key3
| 0x2C
   
| 16
 
| 16
 +
| 17
 +
| 30-31
 
|-
 
|-
| sec_boot_dev_sel
+
| public_key3
| 0x2C
+
| 18
| 3
+
| 19
 +
| 0-29
 +
|-
 +
| public_key4
 +
| 18
 +
| 19
 +
| 30-31
 +
|-
 +
| public_key4
 +
| 20
 +
| 21
 +
| 0-29
 +
|-
 +
| public_key5
 +
| 20
 +
| 21
 +
| 30-31
 +
|-
 +
| public_key5
 +
| 22
 +
| 23
 +
| 0-29
 +
|-
 +
| public_key6
 +
| 22
 +
| 23
 +
| 30-31
 +
|-
 +
| public_key6
 +
| 24
 +
| 25
 +
| 0-29
 +
|-
 +
| public_key7
 +
| 24
 +
| 25
 +
| 30-31
 +
|-
 +
| public_key7
 +
| 26
 +
| 27
 +
| 0-29
 +
|-
 +
| private_key0
 +
| 34
 +
| 35
 +
| 12-31
 +
|-
 +
| private_key0
 +
| 36
 +
| 37
 +
| 0-11
 +
|-
 +
| private_key1
 +
| 36
 +
| 37
 +
| 12-31
 +
|-
 +
| private_key1
 +
| 38
 +
| 39
 +
| 0-11
 +
|-
 +
| private_key2
 +
| 38
 +
| 39
 +
| 12-31
 +
|-
 +
| private_key2
 +
| 40
 +
| 41
 +
| 0-11
 +
|-
 +
| private_key3
 +
| 40
 +
| 41
 +
| 12-31
 +
|-
 +
| private_key3
 +
| 42
 +
| 43
 +
| 0-11
 +
|-
 +
| private_key4
 +
| 42
 +
| 43
 +
| 12-31
 +
|-
 +
| private_key4
 +
| 44
 +
| 45
 +
| 0-11
 +
|-
 +
| boot_device_info
 +
| 44
 +
| 45
 +
| 12-27
 +
|-
 +
| reserved_sw
 +
| 44
 +
| 45
 +
| 28-31
 +
|-
 +
| reserved_sw
 +
| 46
 +
| 47
 +
| 0-3
 +
|-
 +
| reserved_odm0
 +
| 46
 +
| 47
 +
| 5-31
 +
|-
 +
| reserved_odm0
 +
| 48
 +
| 49
 +
| 0-4
 +
|-
 +
| reserved_odm1
 +
| 48
 +
| 49
 +
| 5-31
 +
|-
 +
| reserved_odm1
 +
| 50
 +
| 51
 +
| 0-4
 +
|-
 +
| reserved_odm2
 +
| 50
 +
| 51
 +
| 5-31
 +
|-
 +
| reserved_odm2
 +
| 52
 +
| 53
 +
| 0-4
 +
|-
 +
| reserved_odm3
 +
| 52
 +
| 53
 +
| 5-31
 +
|-
 +
| reserved_odm3
 +
| 54
 +
| 55
 +
| 0-4
 +
|-
 +
| reserved_odm4
 +
| 54
 +
| 55
 +
| 5-31
 +
|-
 +
| reserved_odm4
 +
| 56
 +
| 57
 +
| 0-4
 +
|-
 +
| reserved_odm5
 +
| 56
 +
| 57
 +
| 5-31
 +
|-
 +
| reserved_odm5
 +
| 58
 +
| 59
 +
| 0-4
 +
|-
 +
| [[#reserved_odm6|reserved_odm6]]
 +
| 58
 +
| 59
 +
| 5-31
 +
|-
 +
| [[#reserved_odm6|reserved_odm6]]
 +
| 60
 +
| 61
 +
| 0-4
 +
|-
 +
| [[#reserved_odm7|reserved_odm7]]
 +
| 60
 +
| 61
 +
| 5-31
 +
|-
 +
| [[#reserved_odm7|reserved_odm7]]
 +
| 62
 +
| 63
 +
| 0-4
 +
|-
 +
| kfuse_privkey_ctrl
 +
| 64
 +
| 65
 +
| 13-14
 +
|-
 +
| package_info
 +
| 64
 +
| 65
 +
| 15-18
 +
|-
 +
| opt_vendor_code
 +
| 64
 +
| 65
 +
| 19-22
 +
|-
 +
| opt_fab_code
 +
| 64
 +
| 65
 +
| 23-28
 +
|-
 +
| opt_lot_code_0
 +
| 64
 +
| 65
 +
| 29-31
 +
|-
 +
| opt_lot_code_0
 +
| 66
 +
| 67
 +
| 0-28
 +
|-
 +
| opt_lot_code_1
 +
| 66
 +
| 67
 +
| 29-31
 +
|-
 +
| opt_lot_code_1
 +
| 68
 +
| 69
 +
| 0-24
 +
|-
 +
| opt_wafer_id
 +
| 68
 +
| 69
 +
| 25-30
 +
|-
 +
| opt_x_coordinate
 +
| 68
 +
| 69
 +
| 31
 +
|-
 +
| opt_x_coordinate
 +
| 70
 +
| 71
 +
| 0-7
 +
|-
 +
| opt_y_coordinate
 +
| 70
 +
| 71
 +
| 8-16
 +
|-
 +
| opt_sec_debug_en
 +
| 70
 +
| 71
 +
| 17
 
|-
 
|-
| sw_reserved
+
| opt_ops_reserved
| 0x2E
+
| 70
| 12
+
| 71
 +
| 18-23
 
|-
 
|-
| ignore_dev_sel_straps
+
| sata_calib
| 0x2E
+
| 70
| 1
+
| 71
 +
| 24-25
 
|-
 
|-
| [[#odm_reserved|odm_reserved]]
+
| opt_priv_sec_en
| 0x2E
+
| 90
| 256
+
| 91
 +
| 8
 
|-
 
|-
 
| pkc_disable
 
| pkc_disable
| 0x52
+
| 90
| 1
+
| 91
 +
| 9
 +
|-
 +
| fuse2tsec_debug_disable
 +
| 90
 +
| 91
 +
| 10
 +
|-
 +
| secure_provision_index
 +
| 90
 +
| 91
 +
| 24-27
 
|-
 
|-
| debug_authentication
+
| secure_provision_info
| 0x5A
+
| 90
| 5
+
| 91
 +
| 28-29
 
|-
 
|-
 
| aid
 
| aid
| 0x67
+
| 103
| 32
+
| None
 +
| 0-31
 
|-
 
|-
| [[#bootrom_ipatch|bootrom_ipatch]]
+
| [[#irom_patch|irom_patch]]
| 0x72
+
| 114
| 624
+
| None
 +
| Variable
 
|}
 
|}
   −
=== odm_reserved ===
+
=== reserved_odm6 ===
The first bootloader only burns fuses in this region.
+
Used for anti-downgrade control.
Both fuse indexes 0x3A (odm_reserved + 0x0C) and 0x3C (odm_reserved + 0x0E) are used for anti-downgrade control. These fuses will have their values cached into [[#FUSE_RESERVED_ODM6|FUSE_RESERVED_ODM6]] and [[#FUSE_RESERVED_ODM7|FUSE_RESERVED_ODM7]].
+
 
 +
=== reserved_odm7 ===
 +
Used for anti-downgrade control.
   −
=== bootrom_ipatch ===
+
=== irom_patch ===
Tegra210 based hardware such as the Switch provides support for bootrom patches. The patch data is burned to the hardware fuse array using a specific format (see [https://gist.github.com/shuffle2/f8728159da100e9df2606d43925de0af shuffle2's ipatch decoder]). The bootrom reads these fuses in order to initialize the IPATCH hardware, which allows overriding data returned for code and data fetches done by BPMP.
+
Tegra210 based hardware such as the Switch provides support for bootrom patches. The patch data is burned to the hardware fuse bitmap using a specific format (see [https://gist.github.com/shuffle2/f8728159da100e9df2606d43925de0af shuffle2's ipatch decoder]). The bootrom reads these fuses in order to initialize the IPATCH hardware, which allows overriding data returned for code and data fetches done by BPMP.
    
The following represents the patch data dumped from a Switch console:
 
The following represents the patch data dumped from a Switch console:
Line 858: Line 1,232:  
RAM:00000000
 
RAM:00000000
 
RAM:00000000 irom_svc_dispatch
 
RAM:00000000 irom_svc_dispatch
RAM:00000000  STMFD  SP!, {R0-R2}                  ; ipatches:
+
RAM:00000000  STMFD  SP!, {R0-R2}                  ; ipatches (new):
 +
RAM:00000000                                        ;  0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
 +
RAM:00000000                                        ;  1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
 +
RAM:00000000                                        ;  2 3797df26    6f2e    df26 : svc #0x26 (offset 0x94)
 +
RAM:00000000                                        ;  3 3b4d2100    769a    2100 : movs r1, #0x00
 +
RAM:00000000                                        ;  4  42bdf2c      856    df2c : svc #0x2c (offset 0xa0)
 +
RAM:00000000                                        ;  5 37aadf42    6f54    df42 : svc #0x42 (offset 0xcc)
 +
RAM:00000000                                        ;  6  972df4b    12e4    df4b : svc #0x4b (offset 0xde)
 +
RAM:00000000                                        ;  7 2293df54    4526    df54 : svc #0x54 (offset 0xf0)
 +
RAM:00000000                                        ;  8 21fadf5d    43f4    df5d : svc #0x5d (offset 0x102)
 +
RAM:00000000                                        ;  9 bba2ac57    17744    ac57 : data
 +
RAM:00000000                                        ; 10 bbac3d19    17758    3d19 : data
 +
RAM:00000000                                        ; 11 1e952001    3d2a    2001 : movs r0, #0x01
 +
RAM:00000000                                        ;
 +
RAM:00000000                                        ; ipatches (old):
 
RAM:00000000                                        ;  0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
 
RAM:00000000                                        ;  0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
 
RAM:00000000                                        ;  1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
 
RAM:00000000                                        ;  1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
Line 1,089: Line 1,477:  
The last 4 patches are exclusive to the Switch, while the remaining ones are often included in most Tegra210 based devices.
 
The last 4 patches are exclusive to the Switch, while the remaining ones are often included in most Tegra210 based devices.
   −
==== ipatch 0 ====
+
==== IROM patch 0 ====
 
This patch configures clock enables and clock gate overrides for new hardware.
 
This patch configures clock enables and clock gate overrides for new hardware.
   Line 1,138: Line 1,526:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 1 ====
+
==== IROM patch 1 ====
 
This patch is a bugfix.
 
This patch is a bugfix.
   Line 1,150: Line 1,538:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 2 ====
+
==== IROM patch 2 ====
 
This patch adjusts USB configurations.
 
This patch adjusts USB configurations.
   Line 1,166: Line 1,554:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 3 ====
+
==== IROM patch 3 ====
 
This patch ensures that waiting on PRC_PENDING from the XUSB_DEV register T_XUSB_DEV_XHCI_PORTSC never fails.
 
This patch ensures that waiting on PRC_PENDING from the XUSB_DEV register T_XUSB_DEV_XHCI_PORTSC never fails.
   −
==== ipatch 4 ====
+
In the second batch of patched units ([[#FUSE_OPT_FT_REV|FUSE_OPT_FT_REV]] set to revision 7.0) this patch has been replaced with a fix for [[Switch_System_Flaws#Hardware|CVE-2018-6242]] (arbitrary copy when handling USB control requests in RCM). By setting R1 to 0 at address 0x0010769A in the bootrom, the upper 16 bits of the USB control request's wLength field are cleared out, effectively limiting the request's size to a maximum of 255 bytes.
 +
 
 +
==== IROM patch 4 ====
 
This patch allows backing up and restoring strapping options for warmboot.
 
This patch allows backing up and restoring strapping options for warmboot.
   Line 1,199: Line 1,589:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 5 ====
+
==== IROM patch 5 ====
 
This patch adjusts USB configurations.
 
This patch adjusts USB configurations.
   Line 1,216: Line 1,606:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 6 ====
+
==== IROM patch 6 ====
 
This patch is a factory backdoor.
 
This patch is a factory backdoor.
   Line 1,239: Line 1,629:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 7 ====
+
==== IROM patch 7 ====
 
This patch is a bugfix.
 
This patch is a bugfix.
   Line 1,271: Line 1,661:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatch 8 ====
+
==== IROM patch 8 ====
 
This patch is a bugfix.
 
This patch is a bugfix.
   Line 1,291: Line 1,681:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
==== ipatches 9 and 10 ====
+
==== IROM patches 9 and 10 ====
 
These patches modify the 256-bit Secure Provisioning AES key with index 0x3A.
 
These patches modify the 256-bit Secure Provisioning AES key with index 0x3A.
   −
==== ipatch 11 ====
+
==== IROM patch 11 ====
 
This patch forces the value of [[Security_Engine|SE_TZRAM_SECURITY]] to be 0x01 instead of restoring it from the saved SE context.
 
This patch forces the value of [[Security_Engine|SE_TZRAM_SECURITY]] to be 0x01 instead of restoring it from the saved SE context.
   Line 1,339: Line 1,729:  
| 1
 
| 1
 
|-
 
|-
| 7.0.0-7.0.1
+
| 7.0.0-8.0.1
 
| 9
 
| 9
 +
| 1
 +
|-
 +
| 8.1.0
 +
| 10
 +
| 1
 +
|-
 +
| 9.0.0-9.0.1
 +
| 11
 
| 1
 
| 1
 
|}
 
|}
Line 1,346: Line 1,744:  
If too many fuses are burnt the bootloader will panic immediately.
 
If too many fuses are burnt the bootloader will panic immediately.
   −
If too few are burnt, the bootloader will enable fuse programming and write the expected value to fuse indexes 0x3A and 0x3C. Afterwards, fuse programming is disabled and the panic value 0x21 is written to PMC_SCRATCH200 register (0x7000EC40). Finally, the watchdog timer is initialized and programmed to force a reset.
+
If too few are burnt, the bootloader will enable fuse programming and write the expected value to fuses [[#reserved_odm6|reserved_odm6]] and [[#reserved_odm7|reserved_odm7]]. Afterwards, fuse programming is disabled and the panic value 0x21 is written to PMC_SCRATCH200 register (0x7000EC40). Finally, the watchdog timer is initialized and programmed to force a reset.
    
On a subsequent boot, after the anti-downgrade fuses are checked again, the PMC_RST_STATUS register (0x7000E5B4) is checked and if set to 0x01 (watchdog reset) the PMC_SCRATCH200 register (0x7000EC40) will be checked for the panic value 0x21.
 
On a subsequent boot, after the anti-downgrade fuses are checked again, the PMC_RST_STATUS register (0x7000E5B4) is checked and if set to 0x01 (watchdog reset) the PMC_SCRATCH200 register (0x7000EC40) will be checked for the panic value 0x21.
 
PMC_RST_STATUS will only be set back to 0 (power on reset) if the fuse count matches the new expected value, otherwise the system will panic.
 
PMC_RST_STATUS will only be set back to 0 (power on reset) if the fuse count matches the new expected value, otherwise the system will panic.