Changes

Jump to navigation Jump to search
23,403 bytes added ,  19:20, 11 June 2020
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 uses the Tegra's fuse driver for accessing one time programmable data.
   −
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 =
 +
The fuse driver is mapped to physical address 0x7000F800 with a total size of 0x400 bytes and exposes several registers for fuse programming.
   −
== Registers ==
+
== Erista ==
Below is a list of fuse driver registers used by the Switch's bootloaders.
+
Registers from 0x7000F800 to 0x7000F800 + 0xFC represent the actual fuse [[#Driver|driver]] which can be used to directly program the hardware fuse bitmap.
   −
=== Driver registers ===
+
Registers from 0x7000F800 + 0x100 (FUSE_CHIP_REG_START_OFFSET) to 0x7000F800 + 0x3FC (FUSE_CHIP_REG_END_OFFSET) represent the fuse [[#Cache|cache]] which holds the sensed values of certain fuses.
 +
 
 +
=== Driver ===
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Name
 
!  Name
Line 49: Line 52:  
| [[#FUSE_WRITE_ACCESS_SW|FUSE_WRITE_ACCESS_SW]]
 
| [[#FUSE_WRITE_ACCESS_SW|FUSE_WRITE_ACCESS_SW]]
 
| 0x7000F830
 
| 0x7000F830
|-
  −
| [[#FUSE_PWR_GOOD_SW|FUSE_PWR_GOOD_SW]]
  −
| 0x7000F834
   
|-
 
|-
 
| [[#FUSE_PRIV2RESHIFT|FUSE_PRIV2RESHIFT]]
 
| [[#FUSE_PRIV2RESHIFT|FUSE_PRIV2RESHIFT]]
Line 140: Line 140:     
FUSE_FUSECTRL_RWL selects the fuse redundancy information row.
 
FUSE_FUSECTRL_RWL selects the fuse redundancy information row.
 +
 +
FUSE_FUSECTRL_TRCS triggers record shifting.
    
FUSE_FUSECTRL_PD_CTRL controls the fuse macro's power down mode.
 
FUSE_FUSECTRL_PD_CTRL controls the fuse macro's power down mode.
Line 145: Line 147:  
FUSE_FUSECTRL_FUSE_SENSE_DONE is set if fuse sensing is completed.
 
FUSE_FUSECTRL_FUSE_SENSE_DONE is set if fuse sensing is completed.
   −
FUSE_FUSECTRL_RECORD_SHIFT_DONE is set if ramrepair shift is completed.
+
FUSE_FUSECTRL_RECORD_SHIFT_DONE is set if record shifting is completed.
    
==== FUSE_FUSEADDR ====
 
==== FUSE_FUSEADDR ====
Line 322: Line 324:     
Controls and returns the status of software writes to the fuse cache registers.
 
Controls and returns the status of software writes to the fuse cache registers.
  −
==== FUSE_PWR_GOOD_SW ====
  −
{| class="wikitable" border="1"
  −
!  Bits
  −
!  Description
  −
|-
  −
| 0
  −
| FUSE_PWR_GOOD_SW_VAL
  −
|}
  −
  −
This register is deprecated and has no effect.
      
==== FUSE_PRIV2RESHIFT ====
 
==== FUSE_PRIV2RESHIFT ====
Line 367: Line 358:  
|-
 
|-
 
| 9
 
| 9
| FUSE_PRIV2RESHIFT_TRIG_1_SCPU_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU0_VAL
 
|-
 
|-
 
| 10
 
| 10
| FUSE_PRIV2RESHIFT_TRIG_1_SL2_TBANK_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU1_VAL
 
|-
 
|-
 
| 11
 
| 11
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU0_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU2_VAL
 
|-
 
|-
 
| 12
 
| 12
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU1_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU3_VAL
 
|-
 
|-
 
| 13
 
| 13
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU2_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK0_VAL
 
|-
 
|-
 
| 14
 
| 14
| FUSE_PRIV2RESHIFT_STATUS_1_FCPU3_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK1_VAL
 
|-
 
|-
 
| 15
 
| 15
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK0_VAL
+
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK2_VAL
 
|-
 
|-
 
| 16
 
| 16
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK1_VAL
  −
|-
  −
| 17
  −
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK2_VAL
  −
|-
  −
| 18
   
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK3_VAL
 
| FUSE_PRIV2RESHIFT_STATUS_1_FL2_TBANK3_VAL
|-
  −
| 19
  −
| FUSE_PRIV2RESHIFT_STATUS_1_SCPU_VAL
  −
|-
  −
| 20
  −
| FUSE_PRIV2RESHIFT_STATUS_1_SL2_TBANK_VAL
   
|}
 
|}
   −
Controls and returns the status of the RESHIFT hardware block used in RAM repair.
+
Controls and returns the status of the record shift (RESHIFT) hardware block used for RAM re-repair.
    
==== FUSE_FUSETIME_RD3 ====
 
==== FUSE_FUSETIME_RD3 ====
Line 471: Line 450:  
Returns whether [[#Bitmap|private_key4]] is empty or not.
 
Returns whether [[#Bitmap|private_key4]] is empty or not.
   −
=== Cache registers ===
+
=== Cache ===
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Name
 
!  Name
Line 497: Line 476:  
| 0x7000F918
 
| 0x7000F918
 
|-
 
|-
| FUSE_DAC_CRT_CALIB
+
| [[#FUSE_OPT_FT_REV|FUSE_OPT_FT_REV]]
| 0x7000F91C
  −
|-
  −
| FUSE_DAC_HDTV_CALIB
  −
| 0x7000F920
  −
|-
  −
| FUSE_DAC_SDTV_CALIB
  −
| 0x7000F924
  −
|-
  −
| [[#FUSE_OPT_FT_REV|FUSE_OPT_FT_REV]]
   
| 0x7000F928
 
| 0x7000F928
 
|-
 
|-
Line 526: Line 496:  
| FUSE_SOC_IDDQ_CALIB
 
| FUSE_SOC_IDDQ_CALIB
 
| 0x7000F940
 
| 0x7000F940
|-
  −
| FUSE_RESERVED_PRODUCTION_WP
  −
| 0x7000F944
   
|-
 
|-
 
| [[#FUSE_FA|FUSE_FA]]
 
| [[#FUSE_FA|FUSE_FA]]
Line 580: Line 547:  
| FUSE_TSENSOR2_CALIB
 
| FUSE_TSENSOR2_CALIB
 
| 0x7000F988
 
| 0x7000F988
|-
  −
| FUSE_VSENSOR_CALIB
  −
| 0x7000F98C
   
|-
 
|-
 
| [[#FUSE_OPT_CP_REV|FUSE_OPT_CP_REV]]
 
| [[#FUSE_OPT_CP_REV|FUSE_OPT_CP_REV]]
Line 652: Line 616:  
| FUSE_OBS_DIS
 
| FUSE_OBS_DIS
 
| 0x7000F9E8
 
| 0x7000F9E8
|-
  −
| FUSE_NOR_INFO
  −
| 0x7000F9EC
   
|-
 
|-
 
| FUSE_USB_CALIB
 
| FUSE_USB_CALIB
Line 704: Line 665:  
| 0x7000FA2C
 
| 0x7000FA2C
 
|-
 
|-
| FUSE_SKU_BOND_OUT_L
+
| FUSE_CLOCK_BOUNDOUT0
 
| 0x7000FA30
 
| 0x7000FA30
 
|-
 
|-
| FUSE_SKU_BOND_OUT_H
+
| FUSE_CLOCK_BOUNDOUT1
 
| 0x7000FA34
 
| 0x7000FA34
|-
  −
| FUSE_SKU_BOND_OUT_U
  −
| 0x7000FA38
  −
|-
  −
| FUSE_SKU_BOND_OUT_V
  −
| 0x7000FA3C
  −
|-
  −
| FUSE_SKU_BOND_OUT_W
  −
| 0x7000FA40
   
|-
 
|-
 
| FUSE_OPT_SAMPLE_TYPE
 
| FUSE_OPT_SAMPLE_TYPE
Line 880: Line 832:  
| FUSE_RESERVED_FIELD
 
| FUSE_RESERVED_FIELD
 
| 0x7000FB54
 
| 0x7000FB54
|-
  −
| FUSE_OPT_ECC_EN
  −
| 0x7000FB58
   
|-
 
|-
 
| FUSE_SPARE_REALIGNMENT_REG
 
| FUSE_SPARE_REALIGNMENT_REG
Line 1,020: Line 969:  
|-
 
|-
 
| 3
 
| 3
| Skip device selection straps (0 = don't skip; 1 = skip)
+
| Skip device selection straps
 
|-
 
|-
 
| 4
 
| 4
| ENABLE_CHARGER_DETECT
+
| Enable charger detection
 
|-
 
|-
 
| 5
 
| 5
| ENABLE_WATCHDOG
+
| Enable watchdog
 
|-
 
|-
 
| 6
 
| 6
| Forced RCM two button mode (0 = Only VOLUME_UP; 1 = VOLUME_UP + HOME)
+
| Forced RCM two button mode (0 = VOLUME_UP, 1 = VOLUME_UP + HOME)
 
|-
 
|-
 
| 7
 
| 7
| RCM USB controller mode (0 = USB 2.0; 1 = XUSB)
+
| RCM USB controller mode (0 = USB 2.0, 1 = XUSB)
 
|}
 
|}
   Line 1,040: Line 989:     
==== FUSE_RESERVED_ODM0 ====
 
==== FUSE_RESERVED_ODM0 ====
Stores an hardware ID.
+
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-31
 +
| OdmTestId0
 +
|}
    
==== FUSE_RESERVED_ODM1 ====
 
==== FUSE_RESERVED_ODM1 ====
Stores an hardware ID.
+
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-31
 +
| OdmTestId1
 +
|}
    
==== FUSE_RESERVED_ODM2 ====
 
==== FUSE_RESERVED_ODM2 ====
Line 1,050: Line 1,011:  
!  Description
 
!  Description
 
|-
 
|-
| 0-4
+
| 0-31
| [5.0.0+] Used as key generation (patched units only)
+
| OdmTestId2
 
|}
 
|}
   −
Stores an hardware ID in original launch units, but in patched units it stores a single value (key generation).
+
[5.0.0+] If [[#FUSE_RESERVED_ODM4|FormatVersion]] is 1, this becomes:
 +
 
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-4
 +
| DeviceUniqueKeyGeneration
 +
|-
 +
| 5-31
 +
| Reserved
 +
|}
    
==== FUSE_RESERVED_ODM3 ====
 
==== FUSE_RESERVED_ODM3 ====
Stores an hardware ID in original launch units, but is empty in patched units.
+
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-31
 +
| OdmTestId3
 +
|}
 +
 
 +
[5.0.0+] If [[#FUSE_RESERVED_ODM4|FormatVersion]] is 1, this becomes:
 +
 
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-31
 +
| Reserved
 +
|}
    
==== FUSE_RESERVED_ODM4 ====
 
==== FUSE_RESERVED_ODM4 ====
Line 1,065: Line 1,053:  
|-
 
|-
 
| 0-1
 
| 0-1
| Unit type (0x00 = Retail, 0x03 = Debug)
+
| HardwareState1
 
|-
 
|-
 
| 2
 
| 2
| Production flag (0x00 = Prototype, 0x01 = Production)
+
| HardwareType1
 
|-
 
|-
 
| [1.0.0-3.0.2] 3-5
 
| [1.0.0-3.0.2] 3-5
 
[4.0.0+] 3-7
 
[4.0.0+] 3-7
| DRAM ID
+
| DramId
 
|-
 
|-
 
| 8
 
| 8
| Development flag (0x00 = Retail, 0x01 = Development)
+
| HardwareType2
 
|-
 
|-
 
| 9
 
| 9
| Unit type flag (0x00 = Debug, 0x01 = Retail)
+
| HardwareState2
 
|-
 
|-
 
| 10
 
| 10
| [3.0.0+] Kiosk flag (0x00 = Retail, 0x01 = Kiosk/Quest)
+
| [3.0.0+] QuestState
 
|-
 
|-
 
| 11
 
| 11
| [5.0.0+] Patch flag (0x00 = Unpatched, 1 = Patched)
+
| [5.0.0+] FormatVersion
 
|-
 
|-
 
| 16-19
 
| 16-19
| [4.0.0+] New hardware type (0x00 = Icosa, 0x01 = Iowa, 0x02 = Hoag)
+
| [4.0.0+] HardwareType3
 
|}
 
|}
   −
Stores some device configuration parameters.
+
Stores device configuration parameters.
    
==== FUSE_RESERVED_ODM5 ====
 
==== FUSE_RESERVED_ODM5 ====
Line 1,146: Line 1,134:  
[4.0.0+] This value is no longer used during boot.
 
[4.0.0+] This value is no longer used during boot.
   −
== Bitmap ==
+
== Mariko ==
The actual hardware fuses are stored in a bitmap and may be programmed through the fuse driver after enabling fuse programming.
+
Registers from 0x7000F800 to 0x7000F800 + 0x94 represent the actual fuse [[#Driver_2|driver]] which can be used to directly program the hardware fuse bitmap.
   −
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, spare bits and all fuses afterwards in the fuse bitmap, no longer have a redundant alias.
+
Registers from 0x7000F800 + 0x98 to 0x7000F800 + 0x3FC represent the fuse [[#Cache_2|cache]] which holds the sensed values of certain fuses.
   −
Below is a list of common fuses used by Tegra devices (and applicable to the Switch).
+
=== Driver ===
 +
Same registers as in the Erista's fuse [[#Driver|driver]].
    +
=== Cache ===
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
!  Name
 
!  Name
Number
+
Address
!  Redundant number
+
|-
!  Bits
+
| FUSE_RESERVED_ODM8
 +
| 0x7000F898
 
|-
 
|-
| enable_fuse_program
+
| FUSE_RESERVED_ODM9
| 0
+
| 0x7000F89C
| 1
  −
| 0
   
|-
 
|-
| disable_fuse_program
+
| FUSE_RESERVED_ODM10
| 0
+
| 0x7000F8A0
| 1
+
|-
| 1
+
| FUSE_RESERVED_ODM11
 +
| 0x7000F8A4
 
|-
 
|-
| bypass_fuses
+
| FUSE_RESERVED_ODM12
| 0
+
| 0x7000F8A8
| 1
  −
| 2
   
|-
 
|-
| jtag_direct_access_disable
+
| FUSE_RESERVED_ODM13
| 0
+
| 0x7000F8AC
| 1
  −
| 3
   
|-
 
|-
| production_mode
+
| FUSE_RESERVED_ODM14
| 0
+
| 0x7000F8B0
| 1
  −
| 4
   
|-
 
|-
| jtag_secureid_valid
+
| FUSE_RESERVED_ODM15
| 0
+
| 0x7000F8B4
| 1
  −
| 5
   
|-
 
|-
| odm_lock
+
| FUSE_RESERVED_ODM16
| 0
+
| 0x7000F8B8
| 1
  −
| 6-9
   
|-
 
|-
| fa_mode
+
| FUSE_RESERVED_ODM17
| 0
+
| 0x7000F8BC
| 1
  −
| 10
   
|-
 
|-
| security_mode
+
| FUSE_RESERVED_ODM18
| 0
+
| 0x7000F8C0
| 1
  −
| 11
   
|-
 
|-
| arm_debug_dis
+
| FUSE_RESERVED_ODM19
| 0
+
| 0x7000F8C4
| 1
+
|-
| 12
+
| FUSE_RESERVED_ODM20
 +
| 0x7000F8C8
 +
|-
 +
| FUSE_RESERVED_ODM21
 +
| 0x7000F8CC
 
|-
 
|-
| obs_dis
+
| FUSE_KEK00
| 0
+
| 0x7000F8D0
| 1
  −
| 13
   
|-
 
|-
| public_key0
+
| FUSE_KEK01
| 10
+
| 0x7000F8D4
| 11
  −
| 30-31
   
|-
 
|-
| public_key0
+
| FUSE_KEK02
| 12
+
| 0x7000F8D8
| 13
  −
| 0-29
   
|-
 
|-
| public_key1
+
| FUSE_KEK03
| 12
+
| 0x7000F8DC
| 13
  −
| 30-31
   
|-
 
|-
| public_key1
+
| FUSE_BEK00
| 14
+
| 0x7000F8E0
| 15
  −
| 0-29
   
|-
 
|-
| public_key2
+
| FUSE_BEK01
| 14
+
| 0x7000F8E4
| 15
  −
| 30-31
   
|-
 
|-
| public_key2
+
| FUSE_BEK02
| 16
+
| 0x7000F8E8
| 17
  −
| 0-29
   
|-
 
|-
| public_key3
+
| FUSE_BEK03
| 16
+
| 0x7000F8EC
| 17
  −
| 30-31
   
|-
 
|-
| public_key3
+
|  
| 18
+
| 0x7000F8F0
| 19
  −
| 0-29
   
|-
 
|-
| public_key4
+
|  
| 18
+
| 0x7000F8F4
| 19
  −
| 30-31
   
|-
 
|-
| public_key4
+
|  
| 20
+
| 0x7000F8F8
| 21
  −
| 0-29
   
|-
 
|-
| public_key5
+
|  
| 20
+
| 0x7000F8FC
| 21
  −
| 30-31
   
|-
 
|-
| public_key5
+
| FUSE_PRODUCTION_MODE
| 22
+
| 0x7000F900
| 23
  −
| 0-29
   
|-
 
|-
| public_key6
+
| FUSE_JTAG_SECUREID_VALID
| 22
+
| 0x7000F904
| 23
  −
| 30-31
   
|-
 
|-
| public_key6
+
| FUSE_ODM_LOCK
| 24
+
| 0x7000F908
| 25
+
|-
| 0-29
+
| FUSE_OPT_OPENGL_EN
 +
| 0x7000F90C
 
|-
 
|-
| public_key7
+
| FUSE_SKU_INFO
| 24
+
| 0x7000F910
| 25
  −
| 30-31
   
|-
 
|-
| public_key7
+
| FUSE_CPU_SPEEDO_0_CALIB
| 26
+
| 0x7000F914
| 27
  −
| 0-29
   
|-
 
|-
| private_key0
+
| FUSE_CPU_IDDQ_CALIB
| 34
+
| 0x7000F918
| 35
  −
| 12-31
   
|-
 
|-
| private_key0
+
| FUSE_RESERVED_ODM22
| 36
+
| 0x7000F91C
| 37
  −
| 0-11
   
|-
 
|-
| private_key1
+
| FUSE_RESERVED_ODM23
| 36
+
| 0x7000F920
| 37
  −
| 12-31
   
|-
 
|-
| private_key1
+
| FUSE_RESERVED_ODM24
| 38
+
| 0x7000F924
| 39
  −
| 0-11
   
|-
 
|-
| private_key2
+
| FUSE_OPT_FT_REV
| 38
+
| 0x7000F928
| 39
  −
| 12-31
   
|-
 
|-
| private_key2
+
| FUSE_CPU_SPEEDO_1_CALIB
| 40
+
| 0x7000F92C
| 41
  −
| 0-11
   
|-
 
|-
| private_key3
+
| FUSE_CPU_SPEEDO_2_CALIB
| 40
+
| 0x7000F930
| 41
  −
| 12-31
   
|-
 
|-
| private_key3
+
| FUSE_SOC_SPEEDO_0_CALIB
| 42
+
| 0x7000F934
| 43
  −
| 0-11
   
|-
 
|-
| private_key4
+
| FUSE_SOC_SPEEDO_1_CALIB
| 42
+
| 0x7000F938
| 43
  −
| 12-31
   
|-
 
|-
| private_key4
+
| FUSE_SOC_SPEEDO_2_CALIB
| 44
+
| 0x7000F93C
| 45
  −
| 0-11
   
|-
 
|-
| boot_device_info
+
| FUSE_SOC_IDDQ_CALIB
| 44
+
| 0x7000F940
| 45
  −
| 12-27
   
|-
 
|-
| reserved_sw
+
| FUSE_RESERVED_ODM25
| 44
+
| 0x7000F944
| 45
  −
| 28-31
   
|-
 
|-
| reserved_sw
+
| FUSE_FA
| 46
+
| 0x7000F948
| 47
  −
| 0-3
   
|-
 
|-
| reserved_odm0
+
| FUSE_RESERVED_PRODUCTION
| 46
+
| 0x7000F94C
| 47
  −
| 5-31
   
|-
 
|-
| reserved_odm0
+
| FUSE_HDMI_LANE0_CALIB
| 48
+
| 0x7000F950
| 49
  −
| 0-4
   
|-
 
|-
| reserved_odm1
+
| FUSE_HDMI_LANE1_CALIB
| 48
+
| 0x7000F954
| 49
  −
| 5-31
   
|-
 
|-
| reserved_odm1
+
| FUSE_HDMI_LANE2_CALIB
| 50
+
| 0x7000F958
| 51
  −
| 0-4
   
|-
 
|-
| reserved_odm2
+
| FUSE_HDMI_LANE3_CALIB
| 50
+
| 0x7000F95C
| 51
  −
| 5-31
   
|-
 
|-
| reserved_odm2
+
| FUSE_ENCRYPTION_RATE
| 52
+
| 0x7000F960
| 53
  −
| 0-4
   
|-
 
|-
| reserved_odm3
+
| FUSE_PUBLIC_KEY0
| 52
+
| 0x7000F964
| 53
  −
| 5-31
   
|-
 
|-
| reserved_odm3
+
| FUSE_PUBLIC_KEY1
| 54
+
| 0x7000F968
| 55
  −
| 0-4
   
|-
 
|-
| reserved_odm4
+
| FUSE_PUBLIC_KEY2
| 54
+
| 0x7000F96C
| 55
  −
| 5-31
   
|-
 
|-
| reserved_odm4
+
| FUSE_PUBLIC_KEY3
| 56
+
| 0x7000F970
| 57
  −
| 0-4
   
|-
 
|-
| reserved_odm5
+
| FUSE_PUBLIC_KEY4
| 56
+
| 0x7000F974
| 57
  −
| 5-31
   
|-
 
|-
| reserved_odm5
+
| FUSE_PUBLIC_KEY5
| 58
+
| 0x7000F978
| 59
  −
| 0-4
   
|-
 
|-
| [[#reserved_odm6|reserved_odm6]]
+
| FUSE_PUBLIC_KEY6
| 58
+
| 0x7000F97C
| 59
  −
| 5-31
   
|-
 
|-
| [[#reserved_odm6|reserved_odm6]]
+
| FUSE_PUBLIC_KEY7
| 60
+
| 0x7000F980
| 61
  −
| 0-4
   
|-
 
|-
| [[#reserved_odm7|reserved_odm7]]
+
| FUSE_TSENSOR1_CALIB
| 60
+
| 0x7000F984
| 61
  −
| 5-31
   
|-
 
|-
| [[#reserved_odm7|reserved_odm7]]
+
| FUSE_TSENSOR2_CALIB
| 62
+
| 0x7000F988
| 63
  −
| 0-4
   
|-
 
|-
| kfuse_privkey_ctrl
+
| FUSE_OPT_SECURE_SCC_DIS
| 64
+
| 0x7000F98C
| 65
  −
| 13-14
   
|-
 
|-
| package_info
+
| FUSE_OPT_CP_REV
| 64
+
| 0x7000F990
| 65
  −
| 15-18
   
|-
 
|-
| opt_vendor_code
+
| FUSE_OPT_PFG
| 64
+
| 0x7000F994
| 65
  −
| 19-22
   
|-
 
|-
| opt_fab_code
+
| FUSE_TSENSOR0_CALIB
| 64
+
| 0x7000F998
| 65
  −
| 23-28
   
|-
 
|-
| opt_lot_code_0
+
| FUSE_FIRST_BOOTROM_PATCH_SIZE
| 64
+
| 0x7000F99C
| 65
  −
| 29-31
   
|-
 
|-
| opt_lot_code_0
+
| FUSE_SECURITY_MODE
| 66
+
| 0x7000F9A0
| 67
  −
| 0-28
   
|-
 
|-
| opt_lot_code_1
+
| FUSE_PRIVATE_KEY0
| 66
+
| 0x7000F9A4
| 67
  −
| 29-31
   
|-
 
|-
| opt_lot_code_1
+
| FUSE_PRIVATE_KEY1
| 68
+
| 0x7000F9A8
| 69
  −
| 0-24
   
|-
 
|-
| opt_wafer_id
+
| FUSE_PRIVATE_KEY2
| 68
+
| 0x7000F9AC
| 69
  −
| 25-30
   
|-
 
|-
| opt_x_coordinate
+
| FUSE_PRIVATE_KEY3
| 68
+
| 0x7000F9B0
| 69
  −
| 31
   
|-
 
|-
| opt_x_coordinate
+
| FUSE_PRIVATE_KEY4
| 70
+
| 0x7000F9B4
| 71
  −
| 0-7
   
|-
 
|-
| opt_y_coordinate
+
| FUSE_ARM_JTAG_DIS
| 70
+
| 0x7000F9B8
| 71
+
|-
| 8-16
+
| FUSE_BOOT_DEVICE_INFO
 +
| 0x7000F9BC
 
|-
 
|-
| opt_sec_debug_en
+
| FUSE_RESERVED_SW
| 70
+
| 0x7000F9C0
| 71
  −
| 17
   
|-
 
|-
| opt_ops_reserved
+
| FUSE_OPT_VP9_DISABLE
| 70
+
| 0x7000F9C4
| 71
  −
| 18-23
   
|-
 
|-
| sata_calib
+
| FUSE_RESERVED_ODM0
| 70
+
| 0x7000F9C8
| 71
  −
| 24-25
   
|-
 
|-
| opt_priv_sec_en
+
| FUSE_RESERVED_ODM1
| 90
+
| 0x7000F9CC
| 91
  −
| 8
   
|-
 
|-
| pkc_disable
+
| FUSE_RESERVED_ODM2
| 90
+
| 0x7000F9D0
| 91
  −
| 9
   
|-
 
|-
| fuse2tsec_debug_disable
+
| FUSE_RESERVED_ODM3
| 90
+
| 0x7000F9D4
| 91
+
|-
| 10
+
| FUSE_RESERVED_ODM4
 +
| 0x7000F9D8
 
|-
 
|-
| secure_provision_index
+
| FUSE_RESERVED_ODM5
| 90
+
| 0x7000F9DC
| 91
  −
| 24-27
   
|-
 
|-
| secure_provision_info
+
| FUSE_RESERVED_ODM6
| 90
+
| 0x7000F9E0
| 91
  −
| 28-29
   
|-
 
|-
| spare_bit_0
+
| FUSE_RESERVED_ODM7
| 100
+
| 0x7000F9E4
| None
  −
| 16
   
|-
 
|-
| spare_bit_1
+
| FUSE_OBS_DIS
| 100
+
| 0x7000F9E8
| None
  −
| 17
   
|-
 
|-
| spare_bit_2
+
|  
| 100
+
| 0x7000F9EC
| None
  −
| 18
   
|-
 
|-
| spare_bit_3
+
| FUSE_USB_CALIB
| 100
+
| 0x7000F9F0
| None
  −
| 19
   
|-
 
|-
| spare_bit_4
+
| FUSE_SKU_DIRECT_CONFIG
| 100
+
| 0x7000F9F4
| None
  −
| 20
   
|-
 
|-
| spare_bit_5
+
| FUSE_KFUSE_PRIVKEY_CTRL
| 100
+
| 0x7000F9F8
| None
  −
| 21
   
|-
 
|-
| spare_bit_6
+
| FUSE_PACKAGE_INFO
| 100
+
| 0x7000F9FC
| None
  −
| 22
   
|-
 
|-
| spare_bit_7
+
| FUSE_OPT_VENDOR_CODE
| 100
+
| 0x7000FA00
| None
  −
| 23
   
|-
 
|-
| spare_bit_8
+
| FUSE_OPT_FAB_CODE
| 100
+
| 0x7000FA04
| None
  −
| 24
   
|-
 
|-
| spare_bit_9
+
| FUSE_OPT_LOT_CODE_0
| 100
+
| 0x7000FA08
| None
+
|-
| 25
+
| FUSE_OPT_LOT_CODE_1
 +
| 0x7000FA0C
 
|-
 
|-
| spare_bit_10
+
| FUSE_OPT_WAFER_ID
| 100
+
| 0x7000FA10
| None
  −
| 26
   
|-
 
|-
| spare_bit_11
+
| FUSE_OPT_X_COORDINATE
| 100
+
| 0x7000FA14
| None
  −
| 27
   
|-
 
|-
| spare_bit_12
+
| FUSE_OPT_Y_COORDINATE
| 100
+
| 0x7000FA18
| None
  −
| 28
   
|-
 
|-
| spare_bit_13
+
| FUSE_OPT_SEC_DEBUG_EN
| 100
+
| 0x7000FA1C
| None
  −
| 29
   
|-
 
|-
| spare_bit_14
+
| FUSE_OPT_OPS_RESERVED
| 100
+
| 0x7000FA20
| None
+
|-
| 30
+
|  
 +
| 0x7000FA24
 
|-
 
|-
| spare_bit_15
+
| FUSE_GPU_IDDQ_CALIB
| 100
+
| 0x7000FA28
| None
  −
| 31
   
|-
 
|-
| spare_bit_16
+
| FUSE_TSENSOR3_CALIB
| 101
+
| 0x7000FA2C
| None
  −
| 16
   
|-
 
|-
| spare_bit_17
+
| FUSE_CLOCK_BONDOUT0
| 101
+
| 0x7000FA30
| None
  −
| 17
   
|-
 
|-
| spare_bit_18
+
| FUSE_CLOCK_BONDOUT1
| 101
+
| 0x7000FA34
| None
  −
| 18
   
|-
 
|-
| spare_bit_19
+
| FUSE_RESERVED_ODM26
| 101
+
| 0x7000FA38
| None
  −
| 19
   
|-
 
|-
| spare_bit_20
+
| FUSE_RESERVED_ODM27
| 101
+
| 0x7000FA3C
| None
  −
| 20
   
|-
 
|-
| spare_bit_21
+
| [[#FUSE_RESERVED_ODM28|FUSE_RESERVED_ODM28]]
| 101
+
| 0x7000FA40
| None
  −
| 21
   
|-
 
|-
| spare_bit_22
+
| FUSE_OPT_SAMPLE_TYPE
| 101
+
| 0x7000FA44
| None
  −
| 22
   
|-
 
|-
| spare_bit_23
+
| FUSE_OPT_SUBREVISION
| 101
+
| 0x7000FA48
| None
  −
| 23
   
|-
 
|-
| spare_bit_24
+
| FUSE_OPT_SW_RESERVED_0
| 101
+
| 0x7000FA4C
| None
  −
| 24
   
|-
 
|-
| spare_bit_25
+
| FUSE_OPT_SW_RESERVED_1
| 101
+
| 0x7000FA50
| None
  −
| 25
   
|-
 
|-
| spare_bit_26
+
| FUSE_TSENSOR4_CALIB
| 101
+
| 0x7000FA54
| None
+
|-
| 26
+
| FUSE_TSENSOR5_CALIB
 +
| 0x7000FA58
 
|-
 
|-
| spare_bit_27
+
| FUSE_TSENSOR6_CALIB
| 101
+
| 0x7000FA5C
| None
  −
| 27
   
|-
 
|-
| spare_bit_28
+
| FUSE_TSENSOR7_CALIB
| 101
+
| 0x7000FA60
| None
  −
| 28
   
|-
 
|-
| spare_bit_29
+
| FUSE_OPT_PRIV_SEC_EN
| 101
+
| 0x7000FA64
| None
  −
| 29
   
|-
 
|-
| spare_bit_30
+
| [[#FUSE_BOOT_SECURITY_INFO|FUSE_BOOT_SECURITY_INFO]]
| 101
+
| 0x7000FA68
| None
  −
| 30
   
|-
 
|-
| spare_bit_31
+
|  
| 101
+
| 0x7000FA6C
| None
  −
| 31
   
|-
 
|-
| aid
+
|  
| 103
+
| 0x7000FA70
| None
  −
| 2-31
   
|-
 
|-
| aid
+
|  
| 104
+
| 0x7000FA74
| None
  −
| 0-1
   
|-
 
|-
| ramrepair_record0
+
|  
| 106
+
| 0x7000FA78
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record1
+
| FUSE_FUSE2TSEC_DEBUG_DISABLE
| 107
+
| 0x7000FA7C
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record2
+
| FUSE_TSENSOR_COMMON
| 108
+
| 0x7000FA80
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record3
+
| FUSE_OPT_CP_BIN
| 109
+
| 0x7000FA84
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record4
+
| FUSE_OPT_GPU_DISABLE
| 110
+
| 0x7000FA88
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record5
+
| FUSE_OPT_FT_BIN
| 111
+
| 0x7000FA8C
| None
+
|-
| 0-31
+
| FUSE_OPT_DONE_MAP
 +
| 0x7000FA90
 +
|-
 +
| FUSE_RESERVED_ODM29
 +
| 0x7000FA94
 +
|-
 +
| FUSE_APB2JTAG_DISABLE
 +
| 0x7000FA98
 +
|-
 +
| FUSE_ODM_INFO
 +
| 0x7000FA9C
 +
|-
 +
| FUSE_ARM_CRYPT_DE_FEATURE
 +
| 0x7000FAA8
 +
|-
 +
|
 +
| 0x7000FAB0
 
|-
 
|-
| ramrepair_record6
+
|  
| 112
+
| 0x7000FAB4
| None
  −
| 0-31
   
|-
 
|-
| ramrepair_record7
+
|  
| 113
+
| 0x7000FAB8
| None
  −
| 0-31
   
|-
 
|-
| [[#irom_patch|irom_patch]]
+
|  
| 114
+
| 0x7000FABC
| None
+
|-
| Variable
+
| FUSE_WOA_SKU_FLAG
|}
+
| 0x7000FAC0
 
+
|-
=== reserved_odm6 ===
+
| FUSE_ECO_RESERVE_1
Used for [[#Anti-downgrade|anti-downgrade]] control.
+
| 0x7000FAC4
 
+
|-
=== reserved_odm7 ===
+
| FUSE_GCPLEX_CONFIG_FUSE
Used for [[#Anti-downgrade|anti-downgrade]] control.
+
| 0x7000FAC8
 
+
|-
=== irom_patch ===
+
| FUSE_PRODUCTION_MONTH
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.
+
| 0x7000FACC
 
+
|-
The following represents the patch data dumped from a Switch console:
+
| FUSE_RAM_REPAIR_INDICATOR
<syntaxhighlight>
+
| 0x7000FAD0
RAM:00000000 ; =============== S U B R O U T I N E =======================================
+
|-
RAM:00000000
+
| FUSE_TSENSOR9_CALIB
RAM:00000000
+
| 0x7000FAD4
RAM:00000000 irom_svc_dispatch
+
|-
RAM:00000000  STMFD  SP!, {R0-R2}                  ; ipatches (new):
+
| FUSE_VMIN_CALIBRATION
RAM:00000000                                        ;  0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
+
| 0x7000FADC
RAM:00000000                                        ;  1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
+
|-
RAM:00000000                                        ;  2 3797df26    6f2e    df26 : svc #0x26 (offset 0x94)
+
| FUSE_AGING_SENSOR_CALIBRATION
RAM:00000000                                        ;  3 3b4d2100    769a    2100 : movs r1, #0x00
+
| 0x7000FAE0
RAM:00000000                                        ;  4  42bdf2c      856    df2c : svc #0x2c (offset 0xa0)
+
|-
RAM:00000000                                        ;  5 37aadf42    6f54    df42 : svc #0x42 (offset 0xcc)
+
| FUSE_DEBUG_AUTHENTICATION
RAM:00000000                                        ;  6  972df4b    12e4    df4b : svc #0x4b (offset 0xde)
+
| 0x7000FAE4
RAM:00000000                                        ;  7 2293df54    4526    df54 : svc #0x54 (offset 0xf0)
+
|-
RAM:00000000                                        ;  8 21fadf5d    43f4    df5d : svc #0x5d (offset 0x102)
+
| FUSE_SECURE_PROVISION_INDEX
RAM:00000000                                        ;  9 bba2ac57    17744    ac57 : data
+
| 0x7000FAE8
RAM:00000000                                        ; 10 bbac3d19    17758    3d19 : data
+
|-
RAM:00000000                                        ; 11 1e952001    3d2a    2001 : movs r0, #0x01
+
| FUSE_SECURE_PROVISION_INFO
RAM:00000000                                        ;
+
| 0x7000FAEC
RAM:00000000                                        ; ipatches (old):
+
|-
RAM:00000000                                        ;  0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
+
| FUSE_OPT_GPU_DISABLE_CP1
RAM:00000000                                        ;  1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
+
| 0x7000FAF0
RAM:00000000                                        ;  2 3797df26    6f2e    df26 : svc #0x26 (offset 0x94)
+
|-
RAM:00000000                                        ;  3 7d9e2000    fb3c    2000 : movs r0, #0x00
+
| FUSE_SPARE_ENDIS
RAM:00000000                                        ;  4  42bdf2c      856    df2c : svc #0x2c (offset 0xa0)
+
| 0x7000FAF4
RAM:00000000                                        ;  5 37aadf42    6f54    df42 : svc #0x42 (offset 0xcc)
+
|-
RAM:00000000                                        ;  6  972df4b    12e4    df4b : svc #0x4b (offset 0xde)
+
| FUSE_ECO_RESERVE_0
RAM:00000000                                        ;  7 2293df54    4526    df54 : svc #0x54 (offset 0xf0)
+
| 0x7000FAF8
RAM:00000000                                        ;  8 21fadf5d    43f4    df5d : svc #0x5d (offset 0x102)
+
|-
RAM:00000000                                        ;  9 bba2ac57    17744    ac57 : data
+
| FUSE_RESERVED_CALIB0
RAM:00000000                                        ; 10 bbac3d19    17758    3d19 : data
+
| 0x7000FB04
RAM:00000000                                        ; 11 1e952001    3d2a    2001 : movs r0, #0x01
+
|-
RAM:00000004  MOV    R2, LR
+
| FUSE_RESERVED_CALIB1
RAM:00000008  SUB    R2, R2, #2
+
| 0x7000FB08
RAM:0000000C  LDR    R2, [R2]
+
|-
RAM:00000010  AND    R2, R2, #0xFF
+
| FUSE_OPT_GPU_TPC0_DISABLE
RAM:00000014  MOV    R2, R2,LSL#1
+
| 0x7000FB0C
RAM:00000018  LDR    R0, =0x1007B0
+
|-
RAM:0000001C  LDR    R1, =0x1007F8
+
| FUSE_OPT_GPU_TPC0_DISABLE_CP1
RAM:00000020  SUB    R1, R1, R0
+
| 0x7000FB10
RAM:00000024  LDR    R0, =0x40004C30
+
|-
RAM:00000028  ADD    R0, R0, R1
+
| FUSE_OPT_CPU_DISABLE
RAM:0000002C  ADD    R2, R2, R0
+
| 0x7000FB14
RAM:00000030  ORR    R2, R2, #1
+
|-
RAM:00000034  LDMFD  SP!, {R0,R1}
+
| FUSE_OPT_CPU_DISABLE_CP1
RAM:00000038  BX      R2
+
| 0x7000FB18
RAM:00000038 ; End of function irom_svc_dispatch
+
|-
RAM:00000038
+
| FUSE_TSENSOR10_CALIB
RAM:00000038 ; ---------------------------------------------------------------------------
+
| 0x7000FB1C
RAM:0000003C dword_3C DCD 0x1007B0                  ; DATA XREF: irom_svc_dispatch+18↑r
+
|-
RAM:00000040 dword_40 DCD 0x1007F8                  ; DATA XREF: irom_svc_dispatch+1C↑r
+
| FUSE_TSENSOR10_CALIB_AUX
RAM:00000044 dword_44 DCD 0x40004C30                ; DATA XREF: irom_svc_dispatch+24↑r
+
| 0x7000FB20
RAM:00000048  CODE16
+
|-
RAM:00000048
+
|
RAM:00000048 ; =============== S U B R O U T I N E =======================================
+
| 0x7000FB24
RAM:00000048
+
|-
RAM:00000048
+
|
RAM:00000048 sub_48
+
| 0x7000FB28
RAM:00000048  MOVS    R2, #0                        ; 0  b57df00    16ae    df00 : svc #0x00 (offset 0x48)
+
|-
RAM:0000004A  MVNS    R2, R2
+
|
RAM:0000004C  LDR    R1, =0x60006410
+
| 0x7000FB2C
RAM:0000004E  STR    R2, [R1,#0x30]
+
|-
RAM:00000050  STR    R2, [R1,#0x38]
+
|
RAM:00000052  LDR    R1, =0x600060F8
+
| 0x7000FB30
RAM:00000054  STR    R2, [R1]
+
|-
RAM:00000056  STR    R2, [R1,#4]
+
|
RAM:00000058  LDR    R1, =0x60006284
+
| 0x7000FB34
RAM:0000005A  STR    R2, [R1]
+
|-
RAM:0000005C  STR    R2, [R1,#0x18]
+
| FUSE_OPT_GPU_TPC0_DISABLE_CP2
RAM:0000005E  ADDS    R1, #0x80
+
| 0x7000FB38
RAM:00000060  ADDS    R1, #0x1C
+
|-
RAM:00000062  STR    R2, [R1]
+
| FUSE_OPT_GPU_TPC1_DISABLE
RAM:00000064  STR    R2, [R1,#8]
+
| 0x7000FB3C
RAM:00000066  STR    R2, [R1,#0x10]
+
|-
RAM:00000068  ADDS    R1, #0x80
+
| FUSE_OPT_GPU_TPC1_DISABLE_CP1
RAM:0000006A  STR    R2, [R1]
+
| 0x7000FB40
RAM:0000006C  STR    R2, [R1,#4]
+
|-
RAM:0000006E  LDR    R1, =0x60006554
+
| FUSE_OPT_GPU_TPC1_DISABLE_CP2
RAM:00000070  STR    R2, [R1]
+
| 0x7000FB44
RAM:00000072  MOVS    R2, #0xA0000000
+
|-
RAM:00000076  LDR    R1, =0x60006148
+
| FUSE_OPT_CPU_DISABLE_CP2
RAM:00000078  STR    R2, [R1]
+
| 0x7000FB48
RAM:0000007A  ADDS    R1, #0x38 ; '8'
+
|-
RAM:0000007C  STR    R2, [R1]
+
| FUSE_OPT_GPU_DISABLE_CP2
RAM:0000007E  MOVS    R2, #0xE0000000
+
| 0x7000FB4C
RAM:00000082  LDR    R1, =0x600066A0
+
|-
RAM:00000084  STR    R2, [R1]
+
| FUSE_USB_CALIB_EXT
RAM:00000086  MOVS    R1, #0
+
| 0x7000FB50
RAM:00000088  MOVS    R0, #0xE
+
|-
RAM:0000008A  B      pop_r2_mov_pc_lr
+
| FUSE_RESERVED_FIELD
RAM:0000008A ; End of function sub_48
+
| 0x7000FB54
RAM:0000008A
+
|-
RAM:0000008C
+
| FUSE_SPARE_REALIGNMENT_REG
RAM:0000008C ; =============== S U B R O U T I N E =======================================
+
| 0x7000FB7C
RAM:0000008C
+
|-
RAM:0000008C
+
| FUSE_SPARE_BIT_0
RAM:0000008C sub_8C
+
| 0x7000FB80
RAM:0000008C  LDR    R0, [R1,#0x18]                ; 1 1820df22    3040    df22 : svc #0x22 (offset 0x8c)
+
|-
RAM:0000008E  MOVS    R2, #1
+
| FUSE_SPARE_BIT_1
RAM:00000090  ORRS    R0, R2
+
| 0x7000FB84
RAM:00000092  B      pop_r2_mov_pc_lr
+
|-
RAM:00000092 ; End of function sub_8C
+
| FUSE_SPARE_BIT_2
RAM:00000092
+
| 0x7000FB88
RAM:00000094
+
|-
RAM:00000094 ; =============== S U B R O U T I N E =======================================
+
| FUSE_SPARE_BIT_3
RAM:00000094
+
| 0x7000FB8C
RAM:00000094
+
|-
RAM:00000094 sub_94
+
| FUSE_SPARE_BIT_4
RAM:00000094  LDR    R2, [R4,#0x50]                ; 2 3797df26    6f2e    df26 : svc #0x26 (offset 0x94)
+
| 0x7000FB90
RAM:00000096  ADDS    R2, R2, #2
+
|-
RAM:00000098  STR    R2, [R4,#0x50]
+
| FUSE_SPARE_BIT_5
RAM:0000009A  SUBS    R1, #0x80
+
| 0x7000FB94
RAM:0000009C  STR    R1, [R4,#0x34]
+
|-
RAM:0000009E  B      pop_r2_mov_pc_lr
+
| FUSE_SPARE_BIT_6
RAM:0000009E ; End of function sub_94
+
| 0x7000FB98
RAM:0000009E
+
|-
RAM:000000A0
+
| FUSE_SPARE_BIT_7
RAM:000000A0 ; =============== S U B R O U T I N E =======================================
+
| 0x7000FB9C
RAM:000000A0
+
|-
RAM:000000A0
+
| FUSE_SPARE_BIT_8
RAM:000000A0 sub_A0
+
| 0x7000FBA0
RAM:000000A0
+
|-
RAM:000000A0 ; FUNCTION CHUNK AT RAM:00000148 SIZE 00000004 BYTES
+
| FUSE_SPARE_BIT_9
RAM:000000A0
+
| 0x7000FBA4
RAM:000000A0  MOVS    R0, #0x70000000              ; 4  42bdf2c      856    df2c : svc #0x2c (offset 0xa0)
+
|-
RAM:000000A4  LDR    R6, =dword_7000EF14
+
| FUSE_SPARE_BIT_10
RAM:000000A6  LDR    R2, =dword_7000E5B4
+
| 0x7000FBA8
RAM:000000A8  LDR    R2, [R2]
+
|-
RAM:000000AA  CMP    R2, #0
+
| FUSE_SPARE_BIT_11
RAM:000000AC  BEQ    loc_B4
+
| 0x7000FBAC
RAM:000000AE  LDR    R2, [R6]
+
|-
RAM:000000B0  STR    R2, [R0,#8]
+
| FUSE_SPARE_BIT_12
RAM:000000B2  B      loc_BC
+
| 0x7000FBB0
RAM:000000B4 ; ---------------------------------------------------------------------------
+
|-
RAM:000000B4
+
| FUSE_SPARE_BIT_13
RAM:000000B4 loc_B4                                  ; CODE XREF: sub_A0+C↑j
+
| 0x7000FBB4
RAM:000000B4  LDR    R2, [R0,#8]
+
|-
RAM:000000B6  LSRS    R0, R0, #0x12
+
| FUSE_SPARE_BIT_14
RAM:000000B8  ORRS    R2, R0
+
| 0x7000FBB8
RAM:000000BA  STR    R2, [R6]
+
|-
RAM:000000BC
+
| FUSE_SPARE_BIT_15
RAM:000000BC loc_BC                                  ; CODE XREF: sub_A0+12↑j
+
| 0x7000FBBC
RAM:000000BC  LDR    R6, =dword_7000E9C0
+
|-
RAM:000000BE  LDR    R0, [R6]
+
| FUSE_SPARE_BIT_16
RAM:000000C0  MOVS    R2, #0x4000
+
| 0x7000FBC0
RAM:000000C4  ORRS    R2, R0
+
|-
RAM:000000C6  STR    R2, [R6]
+
| FUSE_SPARE_BIT_17
RAM:000000C8  LDR    R0, [R5,#0x10]
+
| 0x7000FBC4
RAM:000000CA  B      pop_r2_mov_pc_lr
+
|-
RAM:000000CA ; End of function sub_A0
+
| FUSE_SPARE_BIT_18
RAM:000000CA
+
| 0x7000FBC8
RAM:000000CC
+
|-
RAM:000000CC ; =============== S U B R O U T I N E =======================================
+
| FUSE_SPARE_BIT_19
RAM:000000CC
+
| 0x7000FBCC
RAM:000000CC
+
|-
RAM:000000CC sub_CC
+
| FUSE_SPARE_BIT_20
RAM:000000CC  MOVS    R2, #0xF000000                ; 5 37aadf42    6f54    df42 : svc #0x42 (offset 0xcc)
+
| 0x7000FBD0
RAM:000000D0  BICS    R1, R2
+
|-
RAM:000000D2  STR    R1, [R4,#0x10]
+
| FUSE_SPARE_BIT_21
RAM:000000D4  LDR    R1, [R4,#0x50]
+
| 0x7000FBD4
RAM:000000D6  MOVS    R2, #7
+
|-
RAM:000000D8  BICS    R1, R2
+
| FUSE_SPARE_BIT_22
RAM:000000DA  STR    R1, [R4,#0x50]
+
| 0x7000FBD8
RAM:000000DC  B      pop_r2_mov_pc_lr
+
|-
RAM:000000DC ; End of function sub_CC
+
| FUSE_SPARE_BIT_23
RAM:000000DC
+
| 0x7000FBDC
RAM:000000DE
+
|-
RAM:000000DE ; =============== S U B R O U T I N E =======================================
+
| FUSE_SPARE_BIT_24
RAM:000000DE
+
| 0x7000FBE0
RAM:000000DE
+
|-
RAM:000000DE sub_DE
+
| FUSE_SPARE_BIT_25
RAM:000000DE  LDR    R2, =dword_7000FA9C          ; 6  972df4b    12e4    df4b : svc #0x4b (offset 0xde)
+
| 0x7000FBE4
RAM:000000E0  LDR    R2, [R2]
+
|-
RAM:000000E2  LSRS    R2, R2, #8
+
| FUSE_SPARE_BIT_26
RAM:000000E4  LSLS    R2, R2, #1
+
| 0x7000FBE8
RAM:000000E6  LDR    R1, [R4]
+
|-
RAM:000000E8  BICS    R1, R2
+
| FUSE_SPARE_BIT_27
RAM:000000EA  STR    R1, [R4]
+
| 0x7000FBEC
RAM:000000EC  CMP    R0, #0
+
|-
RAM:000000EE  B      pop_r2_mov_pc_lr
+
| FUSE_SPARE_BIT_28
RAM:000000EE ; End of function sub_DE
+
| 0x7000FBF0
RAM:000000EE
+
|-
RAM:000000F0
+
| FUSE_SPARE_BIT_29
RAM:000000F0 ; =============== S U B R O U T I N E =======================================
+
| 0x7000FBF4
RAM:000000F0
+
|}
RAM:000000F0
  −
RAM:000000F0 sub_F0
  −
RAM:000000F0
  −
RAM:000000F0 arg_0=  0
  −
RAM:000000F0
  −
RAM:000000F0  LDR    R0, =0x400049F0              ; 7 2293df54    4526    df54 : svc #0x54 (offset 0xf0)
  −
RAM:000000F2  LDR    R2, [R0]
  −
RAM:000000F4  STR    R2, [SP,#arg_0]
  −
RAM:000000F6  LDR    R0, =0x40010000
  −
RAM:000000F8  LSRS    R2, R2, #17
  −
RAM:000000FA  BEQ    pop_r2_mov_pc_lr              ; if ([0x400049F0] >> 17) == 0) {
  −
RAM:000000FA                                        ;  r2 = [0x400049F0];
  −
RAM:000000FA                                        ; } else {
  −
RAM:000000FC  LDR    R0, =APBDEV_PMC_CNTRL_0
  −
RAM:000000FE  STR    R4, [R0]                      ;  write APBDEV_PMC_CNTRL
  −
RAM:00000100
  −
RAM:00000100 loc_100                                ; CODE XREF: sub_F0:loc_100↓j
  −
RAM:00000100  B      loc_100                      ;  hang
  −
RAM:00000100 ; End of function sub_F0                ; }
  −
RAM:00000100
  −
RAM:00000102
  −
RAM:00000102 ; =============== S U B R O U T I N E =======================================
  −
RAM:00000102
  −
RAM:00000102
  −
RAM:00000102 sub_102
  −
RAM:00000102
  −
RAM:00000102 arg_0=  0
  −
RAM:00000102
  −
RAM:00000102  LDR    R2, =0x40010220              ; 8 21fadf5d    43f4    df5d : svc #0x5d (offset 0x102)
  −
RAM:00000104  STR    R2, [SP,#arg_0]              ; set r2 retval = [0x40010220]
  −
RAM:00000106  LDR    R2, [R2,#0x18]
  −
RAM:00000108  ADDS    R0, #0xFC
  −
RAM:0000010A  STR    R2, [R0,#0x1C]                ; [r0+0x118] = [0x40010220 + 0x18]
  −
RAM:0000010C  B      pop_r2_mov_pc_lr
  −
RAM:0000010C ; End of function sub_102
  −
RAM:0000010C
  −
RAM:0000010C ; ---------------------------------------------------------------------------
  −
RAM:0000010E  DCB    0
  −
RAM:0000010F  DCB    0
  −
RAM:00000110 off_110 DCD 0x60006410                  ; DATA XREF: sub_48+4↑r
  −
RAM:00000114 off_114 DCD 0x600060F8                  ; DATA XREF: sub_48+A↑r
  −
RAM:00000118 off_118 DCD 0x60006284                  ; DATA XREF: sub_48+10↑r
  −
RAM:0000011C off_11C DCD 0x60006554                  ; DATA XREF: sub_48+26↑r
  −
RAM:00000120 off_120 DCD 0x60006148                  ; DATA XREF: sub_48+2E↑r
  −
RAM:00000124 off_124 DCD 0x600066A0                  ; DATA XREF: sub_48+3A↑r
  −
RAM:00000128 off_128 DCD dword_7000EF14              ; DATA XREF: sub_A0+4↑r
  −
RAM:0000012C off_12C DCD dword_7000E5B4              ; DATA XREF: sub_A0+6↑r
  −
RAM:00000130 off_130 DCD dword_7000E9C0              ; DATA XREF: sub_A0:loc_BC↑r
  −
RAM:00000134 off_134 DCD dword_7000FA9C              ; DATA XREF: sub_DE↑r
  −
RAM:00000138 off_138 DCD 0x400049F0                  ; DATA XREF: sub_F0↑r
  −
RAM:0000013C dword_13C DCD 0x40010000                ; DATA XREF: sub_F0+6↑r
  −
RAM:00000140 off_140 DCD APBDEV_PMC_CNTRL_0          ; DATA XREF: sub_F0+C↑r
  −
RAM:00000144 off_144 DCD 0x40010220                  ; DATA XREF: sub_102↑r
  −
RAM:00000148 ; ---------------------------------------------------------------------------
  −
RAM:00000148 ; START OF FUNCTION CHUNK FOR sub_A0
  −
RAM:00000148
  −
RAM:00000148 pop_r2_mov_pc_lr                        ; CODE XREF: sub_48+42↑j
  −
RAM:00000148                                        ; sub_8C+6↑j ...
  −
RAM:00000148  POP    {R2}
  −
RAM:0000014A  MOV    PC, LR
  −
RAM:0000014A ; END OF FUNCTION CHUNK FOR sub_A0
  −
</syntaxhighlight>
     −
The last 4 patches are exclusive to the Switch, while the remaining ones are often included in most Tegra210 based devices.
+
==== FUSE_RESERVED_ODM28 ====
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0
 +
| RegulatorType
 +
|}
 +
 
 +
==== FUSE_BOOT_SECURITY_INFO ====
 +
{| class="wikitable" border="1"
 +
!  Bits
 +
!  Description
 +
|-
 +
| 0-1
 +
| Authentication (0 = AES_CMAC, 1 = PKC_RSA)
 +
|-
 +
| 2
 +
| Encryption (0 = DISABLE, 1 = ENABLE)
 +
|-
 +
| 3
 +
| Fuse encryption (0 = DISABLE, 1 = ENABLE)
 +
|-
 +
| 4-6
 +
| Fuse encryption select (0 = TEST_KEY, 1 = NVIDIA_KEY, 2 to 7 = OEM_KEY_1 to OEM_KEY_6)
 +
|}
 +
 
 +
Stores configuration values for the new boot security mechanism.
 +
 
 +
Mariko units have authentication set to PKC_RSA, encryption enabled, fuse encryption enabled and fuse encryption select set to OEM_KEY_1 (development) or OEM_KEY_2 (retail).
 +
 
 +
= Bitmap =
 +
The actual hardware fuses are stored in a bitmap and may be programmed through the fuse driver after enabling fuse programming.
   −
==== IROM patch 0 ====
+
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, spare bits and all fuses afterwards in the fuse bitmap, no longer have a redundant alias.
This patch configures clock enables and clock gate overrides for new hardware.
     −
<syntaxhighlight lang="c">
+
== Erista ==
  u32 CLK_ENB_H_SET = 0x60006328;
+
{| class="wikitable" border="1"
  u32 CLK_ENB_L_SET = 0x60006320;
+
! Name
  u32 CLK_ENB_U_SET = 0x60006330;
+
! Number
  u32 CLK_ENB_V_SET = 0x60006440;
+
! Redundant number
u32 CLK_ENB_W_SET = 0x60006448;
+
! Bits
u32 CLK_ENB_X_SET = 0x60006284;
+
|-
u32 CLK_ENB_Y_SET = 0x6000629C;
+
| enable_fuse_program
u32 LVL2_CLK_GATE_OVRA = 0x600060F8;
+
| 0
u32 LVL2_CLK_GATE_OVRB = 0x600060FC;
+
| 1
u32 LVL2_CLK_GATE_OVRC = 0x600063A0;
+
| 0
u32 LVL2_CLK_GATE_OVRD = 0x600063A4;
+
|-
u32 LVL2_CLK_GATE_OVRE = 0x60006554;
+
| disable_fuse_program
u32 CLK_SOURCE_VI = 0x60006148;
+
| 0
u32 CLK_SOURCE_HOST1X = 0x60006180;
+
| 1
u32 CLK_SOURCE_NVENC = 0x600066A0;
+
| 1
 
+
|-
// Set all clock enables and overrides
+
| bypass_fuses
*(u32 *)CLK_ENB_V_SET = 0xFFFFFFFF;
+
| 0
*(u32 *)CLK_ENB_W_SET = 0xFFFFFFFF;
+
| 1
*(u32 *)LVL2_CLK_GATE_OVRA = 0xFFFFFFFF;
+
| 2
*(u32 *)LVL2_CLK_GATE_OVRB = 0xFFFFFFFF;
+
|-
*(u32 *)CLK_ENB_X_SET = 0xFFFFFFFF;
+
| jtag_direct_access_disable
*(u32 *)CLK_ENB_Y_SET = 0xFFFFFFFF;
+
| 0
*(u32 *)CLK_ENB_L_SET = 0xFFFFFFFF;
+
| 1
*(u32 *)CLK_ENB_H_SET = 0xFFFFFFFF;
+
| 3
*(u32 *)CLK_ENB_U_SET = 0xFFFFFFFF;
+
|-
*(u32 *)LVL2_CLK_GATE_OVRC = 0xFFFFFFFF;
+
| production_mode
*(u32 *)LVL2_CLK_GATE_OVRD = 0xFFFFFFFF;
+
| 0
*(u32 *)LVL2_CLK_GATE_OVRE = 0xFFFFFFFF;
+
| 1
 
+
| 4
// Set VI, HOST1X and NVENC clock sources to CLK_M
+
|-
*(u32 *)CLK_SOURCE_VI = 0xA0000000;
+
| jtag_secureid_valid
*(u32 *)CLK_SOURCE_HOST1X = 0xA0000000;
+
| 0
*(u32 *)CLK_SOURCE_NVENC = 0xE0000000;
+
| 1
 
+
| 5
/*
+
|-
    Untranslated instructions:
+
| odm_lock
 
+
| 0
    MOVS    R1, #0
+
| 1
    MOVS    R0, #0xE
+
| 6-9
*/
+
|-
+
| fa_mode
return;
+
| 0
</syntaxhighlight>
+
| 1
 
+
| 10
==== IROM patch 1 ====
+
|-
This patch is a bugfix.
+
| security_mode
 
+
| 0
LP0 resume code expects APBDEV_PMC_SCRATCH190_0 to be set to 0x01, but the bootrom didn't set it.
+
| 1
 
+
| 11
<syntaxhighlight lang="c">
+
|-
u32 APBDEV_PMC_SCRATCH190_0 = 0x7000EC18;
+
| arm_debug_dis
u32 pmc_scratch190_val = *(u32 *)APBDEV_PMC_SCRATCH190_0;
+
| 0
+
| 1
return (pmc_scratch190_val | 0x01);
+
| 12
</syntaxhighlight>
+
|-
 
+
| obs_dis
==== IROM patch 2 ====
+
| 0
This patch adjusts USB configurations.
+
| 1
 
+
| 13
<syntaxhighlight lang="c">
+
|-
u32 USB1_UTMIP_SPARE_CFG0_0 = 0x7D000834;
+
| public_key0
u32 USB1_UTMIP_BIAS_CFG2_0 = 0x7D000850;
+
| 10
+
| 11
// Increase UTMIP_HSSQUELCH_LEVEL_NEW by 0x02
+
| 30-31
*(u32 *)USB1_UTMIP_BIAS_CFG2_0 += 0x02;
+
|-
 
+
| public_key0
// Clear FUSE_HS_IREF_CAP_CFG
+
| 12
*(u32 *)USB1_UTMIP_SPARE_CFG0_0 = ((*(u32 *)USB1_UTMIP_SPARE_CFG0_0 & ~(0x118)) - 0x80);
+
| 13
+
| 0-29
return;
+
|-
</syntaxhighlight>
+
| public_key1
 
+
| 12
==== IROM patch 3 ====
+
| 13
This patch ensures that waiting on PRC_PENDING from the XUSB_DEV register T_XUSB_DEV_XHCI_PORTSC never fails.
+
| 30-31
 
+
|-
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.
+
| public_key1
 
+
| 14
==== IROM patch 4 ====
+
| 15
This patch allows backing up and restoring strapping options for warmboot.
+
| 0-29
 
+
|-
<syntaxhighlight lang="c">
+
| public_key2
u32 APBDEV_PMC_SCRATCH0_0 = 0x7000E450;
+
| 14
u32 APBDEV_PMC_RST_STATUS_0 = 0x7000E5B4;
+
| 15
u32 APBDEV_PMC_SEC_DISABLE8_0 = 0x7000E9C0;
+
| 30-31
u32 APBDEV_PMC_SECURE_SCRATCH111_0 = 0x7000EF14;
+
|-
u32 APB_MISC_PP_STRAPPING_OPT_A_0 = 0x70000008;
+
| public_key2
 
+
| 16
u32 reset_status = *(u32 *)APBDEV_PMC_RST_STATUS_0;
+
| 17
 
+
| 0-29
// Check for regular power on
+
|-
if (reset_status == 0)
+
| public_key3
{   
+
| 16
    // Set all buttons in RCM_STRAPS and backup to PMC scratch
+
| 17
    *(u32 *)APBDEV_PMC_SECURE_SCRATCH111_0 = (*(u32 *)APB_MISC_PP_STRAPPING_OPT_A_0 | 0x1C00);
+
| 30-31
}
+
|-
else
+
| public_key3
{
+
| 18
    // Restore strapping options from PMC scratch
+
| 19
    *(u32 *)APB_MISC_PP_STRAPPING_OPT_A_0 = *(u32 *)APBDEV_PMC_SECURE_SCRATCH111_0;
+
| 0-29
}
+
|-
 
+
| public_key4
// Disable write access to APBDEV_PMC_SECURE_SCRATCH111_0
+
| 18
*(u32 *)APBDEV_PMC_SEC_DISABLE8_0 |= 0x4000;
+
| 19
+
| 30-31
return *(u32 *)APBDEV_PMC_SCRATCH0_0;
+
|-
</syntaxhighlight>
+
| public_key4
 
+
| 20
==== IROM patch 5 ====
+
| 21
This patch adjusts USB configurations.
+
| 0-29
 
+
|-
<syntaxhighlight lang="c">
+
| public_key5
u32 USB1_UTMIP_HSRX_CFG0_0 = 0x7D000810;
+
| 20
u32 USB1_UTMIP_BIAS_CFG2_0 = 0x7D000850;
+
| 21
 
+
| 30-31
// Clear UTMIP_IDLE_WAIT, UTMIP_ELASTIC_LIMIT and UTMIP_PCOUNT_UPDN_DIV,
+
|-
// and set UTMIP_IDLE_WAIT to 0x11 and UTMIP_ELASTIC_LIMIT to 0x10
+
| public_key5
*(u32 *)USB1_UTMIP_HSRX_CFG0_0 = ((*(u32 *)USB1_UTMIP_HSRX_CFG0_0 & ~(0xF8000) + 0x88000 & ~(0x7C00) + 0x4000) & ~(0xF000000));
+
| 22
+
| 23
// Clear UTMIP_HSSQUELCH_LEVEL_NEW
+
| 0-29
*(u32 *)USB1_UTMIP_BIAS_CFG2_0 &= ~(0x07);
+
|-
+
| public_key6
return;
+
| 22
</syntaxhighlight>
+
| 23
 
+
| 30-31
==== IROM patch 6 ====
+
|-
This patch is a factory backdoor.
+
| public_key6
 
+
| 24
It allows controlling the debug authentication configuration using a fuse.
+
| 25
 
+
| 0-29
<syntaxhighlight lang="c">
+
|-
u32 FUSE_ODM_INFO = 0x7000FA9C;
+
| public_key7
 
+
| 24
u32 odm_info = *(u32 *)FUSE_ODM_INFO;
+
| 25
debug_auth_override_val = ((odm_info >> 0x08) << 0x01);
+
| 30-31
 
+
|-
// Override debug authentication value stored in IRAM
+
| public_key7
*(u32 *)0x400028E4 &= ~(debug_auth_override_val);
+
| 26
 
+
| 27
/*
+
| 0-29
    Untranslated instructions:
+
|-
+
| private_key0
    CMP    R0, #0
+
| 34
*/
+
| 35
+
| 12-31
return;
+
|-
</syntaxhighlight>
+
| private_key0
 
+
| 36
==== IROM patch 7 ====
+
| 37
This patch is a bugfix.
+
| 0-11
 
+
|-
It prevents overflowing IRAM (0x40010000) when copying the warmboot binary from DRAM.
+
| private_key1
 
+
| 36
<syntaxhighlight lang="c">
+
| 37
u32 APBDEV_PMC_CNTRL_0 = 0x7000E400;
+
| 12-31
+
|-
u32 warmboot_header_addr = 0x400049F0;
+
| private_key1
u32 warmboot_bin_size = *(u32 *)warmboot_bin_header_addr;
+
| 38
+
| 39
// Invalid warmboot binary size
+
| 0-11
if (warmboot_size >> 0x11)
+
|-
{
+
| private_key2
    // Assert MAIN_RST
+
| 38
    // 0x40004BF0 comes from R4 and the bootrom doesn't bother to change it
+
| 39
    *(u32 *)APBDEV_PMC_CNTRL_0 = 0x40004BF0;
+
| 12-31
 
+
|-
    // Deadlock
+
| private_key2
    while(1);
+
| 40
}
+
| 41
+
| 0-11
/*
+
|-
    Untranslated instructions:
+
| private_key3
+
| 40
    LDR    R0, =0x40010000
+
| 41
    LDR    R2, [warmboot_bin_header_addr]
+
| 12-31
*/
+
|-
 
+
| private_key3
return;
+
| 42
</syntaxhighlight>
+
| 43
 
+
| 0-11
==== IROM patch 8 ====
+
|-
This patch is a bugfix.
+
| private_key4
 
+
| 42
It sets the correct warmboot binary entrypoint address for RSA signature verification, which would be done in DRAM instead of IRAM without this patch.
+
| 43
 
+
| 12-31
<syntaxhighlight lang="c">
+
|-
u32 warmboot_addr_ptr = 0x40010238;
+
| private_key4
u32 warmboot_entry_addr_ptr = 0x40004C28;
+
| 44
 
+
| 45
*(u32 *)warmboot_entry_addr_ptr = *(u32 *)warmboot_addr_ptr;
+
| 0-11
 
+
|-
/*
+
| boot_device_info
    Untranslated instructions:
+
| 44
+
| 45
    LDR    R2, [warmboot_addr_ptr]
+
| 12-27
  */
+
|-
   
+
| reserved_sw
  return;
+
| 44
</syntaxhighlight>
+
| 45
 
+
| 28-31
==== IROM patches 9 and 10 ====
+
|-
These patches modify the 256-bit Secure Provisioning AES key with index 0x3A.
+
| reserved_sw
 
+
| 46
==== IROM patch 11 ====
+
| 47
This patch forces the value of [[Security_Engine|SE_TZRAM_SECURITY]] to be 0x01 instead of restoring it from the saved SE context.
+
| 0-3
 
+
|-
== Anti-downgrade ==
+
| reserved_odm0
The first bootloader verifies [[#FUSE_RESERVED_ODM7|FUSE_RESERVED_ODM7]] to prevent downgrading.
+
| 46
How many fuses are expected to be burnt depends the device's unit type as below.
+
| 47
 
+
| 5-31
{| class="wikitable" border="1"
+
|-
|-
+
| reserved_odm0
! System version
+
| 48
! Expected number of burnt fuses (retail)
+
| 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
 +
|-
 +
| opt_ops_reserved
 +
| 70
 +
| 71
 +
| 18-23
 +
|-
 +
| sata_calib
 +
| 70
 +
| 71
 +
| 24-25
 +
|-
 +
| opt_priv_sec_en
 +
| 90
 +
| 91
 +
| 8
 +
|-
 +
| pkc_disable
 +
| 90
 +
| 91
 +
| 9
 +
|-
 +
| fuse2tsec_debug_disable
 +
| 90
 +
| 91
 +
| 10
 +
|-
 +
| secure_provision_index
 +
| 90
 +
| 91
 +
| 24-27
 +
|-
 +
| secure_provision_info
 +
| 90
 +
| 91
 +
| 28-29
 +
|-
 +
| spare_bit_0
 +
| 100
 +
| None
 +
| 16
 +
|-
 +
| spare_bit_1
 +
| 100
 +
| None
 +
| 17
 +
|-
 +
| spare_bit_2
 +
| 100
 +
| None
 +
| 18
 +
|-
 +
| spare_bit_3
 +
| 100
 +
| None
 +
| 19
 +
|-
 +
| spare_bit_4
 +
| 100
 +
| None
 +
| 20
 +
|-
 +
| spare_bit_5
 +
| 100
 +
| None
 +
| 21
 +
|-
 +
| spare_bit_6
 +
| 100
 +
| None
 +
| 22
 +
|-
 +
| spare_bit_7
 +
| 100
 +
| None
 +
| 23
 +
|-
 +
| spare_bit_8
 +
| 100
 +
| None
 +
| 24
 +
|-
 +
| spare_bit_9
 +
| 100
 +
| None
 +
| 25
 +
|-
 +
| spare_bit_10
 +
| 100
 +
| None
 +
| 26
 +
|-
 +
| spare_bit_11
 +
| 100
 +
| None
 +
| 27
 +
|-
 +
| spare_bit_12
 +
| 100
 +
| None
 +
| 28
 +
|-
 +
| spare_bit_13
 +
| 100
 +
| None
 +
| 29
 +
|-
 +
| spare_bit_14
 +
| 100
 +
| None
 +
| 30
 +
|-
 +
| spare_bit_15
 +
| 100
 +
| None
 +
| 31
 +
|-
 +
| spare_bit_16
 +
| 101
 +
| None
 +
| 16
 +
|-
 +
| spare_bit_17
 +
| 101
 +
| None
 +
| 17
 +
|-
 +
| spare_bit_18
 +
| 101
 +
| None
 +
| 18
 +
|-
 +
| spare_bit_19
 +
| 101
 +
| None
 +
| 19
 +
|-
 +
| spare_bit_20
 +
| 101
 +
| None
 +
| 20
 +
|-
 +
| spare_bit_21
 +
| 101
 +
| None
 +
| 21
 +
|-
 +
| spare_bit_22
 +
| 101
 +
| None
 +
| 22
 +
|-
 +
| spare_bit_23
 +
| 101
 +
| None
 +
| 23
 +
|-
 +
| spare_bit_24
 +
| 101
 +
| None
 +
| 24
 +
|-
 +
| spare_bit_25
 +
| 101
 +
| None
 +
| 25
 +
|-
 +
| spare_bit_26
 +
| 101
 +
| None
 +
| 26
 +
|-
 +
| spare_bit_27
 +
| 101
 +
| None
 +
| 27
 +
|-
 +
| spare_bit_28
 +
| 101
 +
| None
 +
| 28
 +
|-
 +
| spare_bit_29
 +
| 101
 +
| None
 +
| 29
 +
|-
 +
| spare_bit_30
 +
| 101
 +
| None
 +
| 30
 +
|-
 +
| spare_bit_31
 +
| 101
 +
| None
 +
| 31
 +
|-
 +
| aid
 +
| 103
 +
| None
 +
| 2-31
 +
|-
 +
| aid
 +
| 104
 +
| None
 +
| 0-1
 +
|-
 +
| reshift_fcpu0
 +
| 106
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu1
 +
| 107
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu2
 +
| 108
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu3
 +
| 109
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank0
 +
| 110
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank1
 +
| 111
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank2
 +
| 112
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank3
 +
| 113
 +
| None
 +
| 0-31
 +
|-
 +
| [[#irom_patch|irom_patch]]
 +
| 114
 +
| None
 +
| Variable
 +
|}
 +
 
 +
=== reserved_odm6 ===
 +
Used for [[#Anti-downgrade|anti-downgrade]] control.
 +
 
 +
=== reserved_odm7 ===
 +
Used for [[#Anti-downgrade|anti-downgrade]] control.
 +
 
 +
=== irom_patch ===
 +
Bootrom patches are burned to the hardware fuse bitmap using a specific format (see [https://gist.github.com/hexkyz/98c28e292597d8fc7bef7a2200e792d7 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:
 +
<syntaxhighlight>
 +
RAM:00000000 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000000
 +
RAM:00000000
 +
RAM:00000000 irom_svc_dispatch
 +
RAM:00000000  STMFD  SP!, {R0-R2}                  ; ipatches (new):
 +
RAM:00000000                                        ;  0: 0x0b57df00 0x001016ae 0x0000df00 : svc #0x00 (offset 0x48)
 +
RAM:00000000                                        ;  1: 0x1820df22 0x00103040 0x0000df22 : svc #0x22 (offset 0x8c)
 +
RAM:00000000                                        ;  2: 0x3797df26 0x00106f2e 0x0000df26 : svc #0x26 (offset 0x94)
 +
RAM:00000000                                        ;  3: 0x3b4d2100 0x0010769a 0x00002100 : movs r1, #0x00
 +
RAM:00000000                                        ;  4: 0x042bdf2c 0x00100856 0x0000df2c : svc #0x2c (offset 0xa0)
 +
RAM:00000000                                        ;  5: 0x37aadf42 0x00106f54 0x0000df42 : svc #0x42 (offset 0xcc)
 +
RAM:00000000                                        ;  6: 0x0972df4b 0x001012e4 0x0000df4b : svc #0x4b (offset 0xde)
 +
RAM:00000000                                        ;  7: 0x2293df54 0x00104526 0x0000df54 : svc #0x54 (offset 0xf0)
 +
RAM:00000000                                        ;  8: 0x21fadf5d 0x001043f4 0x0000df5d : svc #0x5d (offset 0x102)
 +
RAM:00000000                                        ;  9: 0xbba2ac57 0x00117744 0x0000ac57 : data
 +
RAM:00000000                                        ; 10: 0xbbac3d19 0x00117758 0x00003d19 : data
 +
RAM:00000000                                        ; 11: 0x1e952001 0x00103d2a 0x00002001 : movs r0, #0x01
 +
RAM:00000000                                        ;
 +
RAM:00000000                                        ; ipatches (old):
 +
RAM:00000000                                        ;  0: 0x0b57df00 0x001016ae 0x0000df00 : svc #0x00 (offset 0x48)
 +
RAM:00000000                                        ;  1: 0x1820df22 0x00103040 0x0000df22 : svc #0x22 (offset 0x8c)
 +
RAM:00000000                                        ;  2: 0x3797df26 0x00106f2e 0x0000df26 : svc #0x26 (offset 0x94)
 +
RAM:00000000                                        ;  3: 0x7d9e2000 0x0010fb3c 0x00002000 : movs r0, #0x00
 +
RAM:00000000                                        ;  4: 0x042bdf2c 0x00100856 0x0000df2c : svc #0x2c (offset 0xa0)
 +
RAM:00000000                                        ;  5: 0x37aadf42 0x00106f54 0x0000df42 : svc #0x42 (offset 0xcc)
 +
RAM:00000000                                        ;  6: 0x0972df4b 0x001012e4 0x0000df4b : svc #0x4b (offset 0xde)
 +
RAM:00000000                                        ;  7: 0x2293df54 0x00104526 0x0000df54 : svc #0x54 (offset 0xf0)
 +
RAM:00000000                                        ;  8: 0x21fadf5d 0x001043f4 0x0000df5d : svc #0x5d (offset 0x102)
 +
RAM:00000000                                        ;  9: 0xbba2ac57 0x00117744 0x0000ac57 : data
 +
RAM:00000000                                        ; 10: 0xbbac3d19 0x00117758 0x00003d19 : data
 +
RAM:00000000                                        ; 11: 0x1e952001 0x00103d2a 0x00002001 : movs r0, #0x01
 +
RAM:00000004  MOV    R2, LR
 +
RAM:00000008  SUB    R2, R2, #2
 +
RAM:0000000C  LDR    R2, [R2]
 +
RAM:00000010  AND    R2, R2, #0xFF
 +
RAM:00000014  MOV    R2, R2,LSL#1
 +
RAM:00000018  LDR    R0, =0x1007B0
 +
RAM:0000001C  LDR    R1, =0x1007F8
 +
RAM:00000020  SUB    R1, R1, R0
 +
RAM:00000024  LDR    R0, =0x40004C30
 +
RAM:00000028  ADD    R0, R0, R1
 +
RAM:0000002C  ADD    R2, R2, R0
 +
RAM:00000030  ORR    R2, R2, #1
 +
RAM:00000034  LDMFD  SP!, {R0,R1}
 +
RAM:00000038  BX      R2
 +
RAM:00000038 ; End of function irom_svc_dispatch
 +
RAM:00000038
 +
RAM:00000038 ; ---------------------------------------------------------------------------
 +
RAM:0000003C dword_3C DCD 0x1007B0                  ; DATA XREF: irom_svc_dispatch+18↑r
 +
RAM:00000040 dword_40 DCD 0x1007F8                  ; DATA XREF: irom_svc_dispatch+1C↑r
 +
RAM:00000044 dword_44 DCD 0x40004C30                ; DATA XREF: irom_svc_dispatch+24↑r
 +
RAM:00000048  CODE16
 +
RAM:00000048
 +
RAM:00000048 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000048
 +
RAM:00000048
 +
RAM:00000048 sub_48
 +
RAM:00000048  MOVS    R2, #0                        ; 0: 0x0b57df00 0x001016ae 0x0000df00 : svc #0x00 (offset 0x48)
 +
RAM:0000004A  MVNS    R2, R2
 +
RAM:0000004C  LDR    R1, =0x60006410
 +
RAM:0000004E  STR    R2, [R1,#0x30]
 +
RAM:00000050  STR    R2, [R1,#0x38]
 +
RAM:00000052  LDR    R1, =0x600060F8
 +
RAM:00000054  STR    R2, [R1]
 +
RAM:00000056  STR    R2, [R1,#4]
 +
RAM:00000058  LDR    R1, =0x60006284
 +
RAM:0000005A  STR    R2, [R1]
 +
RAM:0000005C  STR    R2, [R1,#0x18]
 +
RAM:0000005E  ADDS    R1, #0x80
 +
RAM:00000060  ADDS    R1, #0x1C
 +
RAM:00000062  STR    R2, [R1]
 +
RAM:00000064  STR    R2, [R1,#8]
 +
RAM:00000066  STR    R2, [R1,#0x10]
 +
RAM:00000068  ADDS    R1, #0x80
 +
RAM:0000006A  STR    R2, [R1]
 +
RAM:0000006C  STR    R2, [R1,#4]
 +
RAM:0000006E  LDR    R1, =0x60006554
 +
RAM:00000070  STR    R2, [R1]
 +
RAM:00000072  MOVS    R2, #0xA0000000
 +
RAM:00000076  LDR    R1, =0x60006148
 +
RAM:00000078  STR    R2, [R1]
 +
RAM:0000007A  ADDS    R1, #0x38 ; '8'
 +
RAM:0000007C  STR    R2, [R1]
 +
RAM:0000007E  MOVS    R2, #0xE0000000
 +
RAM:00000082  LDR    R1, =0x600066A0
 +
RAM:00000084  STR    R2, [R1]
 +
RAM:00000086  MOVS    R1, #0
 +
RAM:00000088  MOVS    R0, #0xE
 +
RAM:0000008A  B      pop_r2_mov_pc_lr
 +
RAM:0000008A ; End of function sub_48
 +
RAM:0000008A
 +
RAM:0000008C
 +
RAM:0000008C ; =============== S U B R O U T I N E =======================================
 +
RAM:0000008C
 +
RAM:0000008C
 +
RAM:0000008C sub_8C
 +
RAM:0000008C  LDR    R0, [R1,#0x18]                ; 1: 0x1820df22 0x00103040 0x0000df22 : svc #0x22 (offset 0x8c)
 +
RAM:0000008E  MOVS    R2, #1
 +
RAM:00000090  ORRS    R0, R2
 +
RAM:00000092  B      pop_r2_mov_pc_lr
 +
RAM:00000092 ; End of function sub_8C
 +
RAM:00000092
 +
RAM:00000094
 +
RAM:00000094 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000094
 +
RAM:00000094
 +
RAM:00000094 sub_94
 +
RAM:00000094  LDR    R2, [R4,#0x50]                ; 2: 0x3797df26 0x00106f2e 0x0000df26 : svc #0x26 (offset 0x94)
 +
RAM:00000096  ADDS    R2, R2, #2
 +
RAM:00000098  STR    R2, [R4,#0x50]
 +
RAM:0000009A  SUBS    R1, #0x80
 +
RAM:0000009C  STR    R1, [R4,#0x34]
 +
RAM:0000009E  B      pop_r2_mov_pc_lr
 +
RAM:0000009E ; End of function sub_94
 +
RAM:0000009E
 +
RAM:000000A0
 +
RAM:000000A0 ; =============== S U B R O U T I N E =======================================
 +
RAM:000000A0
 +
RAM:000000A0
 +
RAM:000000A0 sub_A0
 +
RAM:000000A0
 +
RAM:000000A0 ; FUNCTION CHUNK AT RAM:00000148 SIZE 00000004 BYTES
 +
RAM:000000A0
 +
RAM:000000A0  MOVS    R0, #0x70000000              ; 4: 0x042bdf2c 0x00100856 0x0000df2c : svc #0x2c (offset 0xa0)
 +
RAM:000000A4  LDR    R6, =dword_7000EF14
 +
RAM:000000A6  LDR    R2, =dword_7000E5B4
 +
RAM:000000A8  LDR    R2, [R2]
 +
RAM:000000AA  CMP    R2, #0
 +
RAM:000000AC  BEQ    loc_B4
 +
RAM:000000AE  LDR    R2, [R6]
 +
RAM:000000B0  STR    R2, [R0,#8]
 +
RAM:000000B2  B      loc_BC
 +
RAM:000000B4 ; ---------------------------------------------------------------------------
 +
RAM:000000B4
 +
RAM:000000B4 loc_B4                                  ; CODE XREF: sub_A0+C↑j
 +
RAM:000000B4  LDR    R2, [R0,#8]
 +
RAM:000000B6  LSRS    R0, R0, #0x12
 +
RAM:000000B8  ORRS    R2, R0
 +
RAM:000000BA  STR    R2, [R6]
 +
RAM:000000BC
 +
RAM:000000BC loc_BC                                  ; CODE XREF: sub_A0+12↑j
 +
RAM:000000BC  LDR    R6, =dword_7000E9C0
 +
RAM:000000BE  LDR    R0, [R6]
 +
RAM:000000C0  MOVS    R2, #0x4000
 +
RAM:000000C4  ORRS    R2, R0
 +
RAM:000000C6  STR    R2, [R6]
 +
RAM:000000C8  LDR    R0, [R5,#0x10]
 +
RAM:000000CA  B      pop_r2_mov_pc_lr
 +
RAM:000000CA ; End of function sub_A0
 +
RAM:000000CA
 +
RAM:000000CC
 +
RAM:000000CC ; =============== S U B R O U T I N E =======================================
 +
RAM:000000CC
 +
RAM:000000CC
 +
RAM:000000CC sub_CC
 +
RAM:000000CC  MOVS    R2, #0xF000000                ; 5: 0x37aadf42 0x00106f54 0x0000df42 : svc #0x42 (offset 0xcc)
 +
RAM:000000D0  BICS    R1, R2
 +
RAM:000000D2  STR    R1, [R4,#0x10]
 +
RAM:000000D4  LDR    R1, [R4,#0x50]
 +
RAM:000000D6  MOVS    R2, #7
 +
RAM:000000D8  BICS    R1, R2
 +
RAM:000000DA  STR    R1, [R4,#0x50]
 +
RAM:000000DC  B      pop_r2_mov_pc_lr
 +
RAM:000000DC ; End of function sub_CC
 +
RAM:000000DC
 +
RAM:000000DE
 +
RAM:000000DE ; =============== S U B R O U T I N E =======================================
 +
RAM:000000DE
 +
RAM:000000DE
 +
RAM:000000DE sub_DE
 +
RAM:000000DE  LDR    R2, =dword_7000FA9C          ; 6: 0x0972df4b 0x001012e4 0x0000df4b : svc #0x4b (offset 0xde)
 +
RAM:000000E0  LDR    R2, [R2]
 +
RAM:000000E2  LSRS    R2, R2, #8
 +
RAM:000000E4  LSLS    R2, R2, #1
 +
RAM:000000E6  LDR    R1, [R4]
 +
RAM:000000E8  BICS    R1, R2
 +
RAM:000000EA  STR    R1, [R4]
 +
RAM:000000EC  CMP    R0, #0
 +
RAM:000000EE  B      pop_r2_mov_pc_lr
 +
RAM:000000EE ; End of function sub_DE
 +
RAM:000000EE
 +
RAM:000000F0
 +
RAM:000000F0 ; =============== S U B R O U T I N E =======================================
 +
RAM:000000F0
 +
RAM:000000F0
 +
RAM:000000F0 sub_F0
 +
RAM:000000F0
 +
RAM:000000F0 arg_0=  0
 +
RAM:000000F0
 +
RAM:000000F0  LDR    R0, =0x400049F0              ; 7: 0x2293df54 0x00104526 0x0000df54 : svc #0x54 (offset 0xf0)
 +
RAM:000000F2  LDR    R2, [R0]
 +
RAM:000000F4  STR    R2, [SP,#arg_0]
 +
RAM:000000F6  LDR    R0, =0x40010000
 +
RAM:000000F8  LSRS    R2, R2, #17
 +
RAM:000000FA  BEQ    pop_r2_mov_pc_lr              ; if ([0x400049F0] >> 17) == 0) {
 +
RAM:000000FA                                        ;  r2 = [0x400049F0];
 +
RAM:000000FA                                        ; } else {
 +
RAM:000000FC  LDR    R0, =APBDEV_PMC_CNTRL_0
 +
RAM:000000FE  STR    R4, [R0]                      ;  write APBDEV_PMC_CNTRL
 +
RAM:00000100
 +
RAM:00000100 loc_100                                ; CODE XREF: sub_F0:loc_100↓j
 +
RAM:00000100  B      loc_100                      ;  hang
 +
RAM:00000100 ; End of function sub_F0                ; }
 +
RAM:00000100
 +
RAM:00000102
 +
RAM:00000102 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000102
 +
RAM:00000102
 +
RAM:00000102 sub_102
 +
RAM:00000102
 +
RAM:00000102 arg_0=  0
 +
RAM:00000102
 +
RAM:00000102  LDR    R2, =0x40010220              ; 8: 0x21fadf5d 0x001043f4 0x0000df5d : svc #0x5d (offset 0x102)
 +
RAM:00000104  STR    R2, [SP,#arg_0]              ; set r2 retval = [0x40010220]
 +
RAM:00000106  LDR    R2, [R2,#0x18]
 +
RAM:00000108  ADDS    R0, #0xFC
 +
RAM:0000010A  STR    R2, [R0,#0x1C]                ; [r0+0x118] = [0x40010220 + 0x18]
 +
RAM:0000010C  B      pop_r2_mov_pc_lr
 +
RAM:0000010C ; End of function sub_102
 +
RAM:0000010C
 +
RAM:0000010C ; ---------------------------------------------------------------------------
 +
RAM:0000010E  DCB    0
 +
RAM:0000010F  DCB    0
 +
RAM:00000110 off_110 DCD 0x60006410                  ; DATA XREF: sub_48+4↑r
 +
RAM:00000114 off_114 DCD 0x600060F8                  ; DATA XREF: sub_48+A↑r
 +
RAM:00000118 off_118 DCD 0x60006284                  ; DATA XREF: sub_48+10↑r
 +
RAM:0000011C off_11C DCD 0x60006554                  ; DATA XREF: sub_48+26↑r
 +
RAM:00000120 off_120 DCD 0x60006148                  ; DATA XREF: sub_48+2E↑r
 +
RAM:00000124 off_124 DCD 0x600066A0                  ; DATA XREF: sub_48+3A↑r
 +
RAM:00000128 off_128 DCD dword_7000EF14              ; DATA XREF: sub_A0+4↑r
 +
RAM:0000012C off_12C DCD dword_7000E5B4              ; DATA XREF: sub_A0+6↑r
 +
RAM:00000130 off_130 DCD dword_7000E9C0              ; DATA XREF: sub_A0:loc_BC↑r
 +
RAM:00000134 off_134 DCD dword_7000FA9C              ; DATA XREF: sub_DE↑r
 +
RAM:00000138 off_138 DCD 0x400049F0                  ; DATA XREF: sub_F0↑r
 +
RAM:0000013C dword_13C DCD 0x40010000                ; DATA XREF: sub_F0+6↑r
 +
RAM:00000140 off_140 DCD APBDEV_PMC_CNTRL_0          ; DATA XREF: sub_F0+C↑r
 +
RAM:00000144 off_144 DCD 0x40010220                  ; DATA XREF: sub_102↑r
 +
RAM:00000148 ; ---------------------------------------------------------------------------
 +
RAM:00000148 ; START OF FUNCTION CHUNK FOR sub_A0
 +
RAM:00000148
 +
RAM:00000148 pop_r2_mov_pc_lr                        ; CODE XREF: sub_48+42↑j
 +
RAM:00000148                                        ; sub_8C+6↑j ...
 +
RAM:00000148  POP    {R2}
 +
RAM:0000014A  MOV    PC, LR
 +
RAM:0000014A ; END OF FUNCTION CHUNK FOR sub_A0
 +
</syntaxhighlight>
 +
 
 +
The last 4 patches are exclusive to the Switch, while the remaining ones are often included in most Tegra210 based devices.
 +
 
 +
==== IROM patch 0 ====
 +
This patch configures clock enables and clock gate overrides for new hardware.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 CLK_ENB_H_SET = 0x60006328;
 +
u32 CLK_ENB_L_SET = 0x60006320;
 +
u32 CLK_ENB_U_SET = 0x60006330;
 +
u32 CLK_ENB_V_SET = 0x60006440;
 +
u32 CLK_ENB_W_SET = 0x60006448;
 +
u32 CLK_ENB_X_SET = 0x60006284;
 +
u32 CLK_ENB_Y_SET = 0x6000629C;
 +
u32 LVL2_CLK_GATE_OVRA = 0x600060F8;
 +
u32 LVL2_CLK_GATE_OVRB = 0x600060FC;
 +
u32 LVL2_CLK_GATE_OVRC = 0x600063A0;
 +
u32 LVL2_CLK_GATE_OVRD = 0x600063A4;
 +
u32 LVL2_CLK_GATE_OVRE = 0x60006554;
 +
u32 CLK_SOURCE_VI = 0x60006148;
 +
u32 CLK_SOURCE_HOST1X = 0x60006180;
 +
u32 CLK_SOURCE_NVENC = 0x600066A0;
 +
 
 +
// Set all clock enables and overrides
 +
*(u32 *)CLK_ENB_V_SET = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_W_SET = 0xFFFFFFFF;
 +
*(u32 *)LVL2_CLK_GATE_OVRA = 0xFFFFFFFF;
 +
*(u32 *)LVL2_CLK_GATE_OVRB = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_X_SET = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_Y_SET = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_L_SET = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_H_SET = 0xFFFFFFFF;
 +
*(u32 *)CLK_ENB_U_SET = 0xFFFFFFFF;
 +
*(u32 *)LVL2_CLK_GATE_OVRC = 0xFFFFFFFF;
 +
*(u32 *)LVL2_CLK_GATE_OVRD = 0xFFFFFFFF;
 +
*(u32 *)LVL2_CLK_GATE_OVRE = 0xFFFFFFFF;
 +
 
 +
// Set VI, HOST1X and NVENC clock sources to CLK_M
 +
*(u32 *)CLK_SOURCE_VI = 0xA0000000;
 +
*(u32 *)CLK_SOURCE_HOST1X = 0xA0000000;
 +
*(u32 *)CLK_SOURCE_NVENC = 0xE0000000;
 +
 
 +
/*
 +
    Untranslated instructions:
 +
 
 +
    MOVS    R1, #0
 +
    MOVS    R0, #0xE
 +
*/
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 1 ====
 +
This patch is a bugfix.
 +
 
 +
LP0 resume code expects APBDEV_PMC_SCRATCH190_0 to be set to 0x01, but the bootrom didn't set it.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 APBDEV_PMC_SCRATCH190_0 = 0x7000EC18;
 +
u32 pmc_scratch190_val = *(u32 *)APBDEV_PMC_SCRATCH190_0;
 +
 +
return (pmc_scratch190_val | 0x01);
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 2 ====
 +
This patch adjusts USB configurations.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 USB1_UTMIP_SPARE_CFG0_0 = 0x7D000834;
 +
u32 USB1_UTMIP_BIAS_CFG2_0 = 0x7D000850;
 +
 +
// Increase UTMIP_HSSQUELCH_LEVEL_NEW by 0x02
 +
*(u32 *)USB1_UTMIP_BIAS_CFG2_0 += 0x02;
 +
 
 +
// Clear FUSE_HS_IREF_CAP_CFG
 +
*(u32 *)USB1_UTMIP_SPARE_CFG0_0 = ((*(u32 *)USB1_UTMIP_SPARE_CFG0_0 & ~(0x118)) - 0x80);
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 3 ====
 +
This patch ensures that waiting on PRC_PENDING from the XUSB_DEV register T_XUSB_DEV_XHCI_PORTSC never fails.
 +
 
 +
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.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 APBDEV_PMC_SCRATCH0_0 = 0x7000E450;
 +
u32 APBDEV_PMC_RST_STATUS_0 = 0x7000E5B4;
 +
u32 APBDEV_PMC_SEC_DISABLE8_0 = 0x7000E9C0;
 +
u32 APBDEV_PMC_SECURE_SCRATCH111_0 = 0x7000EF14;
 +
u32 APB_MISC_PP_STRAPPING_OPT_A_0 = 0x70000008;
 +
 
 +
u32 reset_status = *(u32 *)APBDEV_PMC_RST_STATUS_0;
 +
 
 +
// Check for regular power on
 +
if (reset_status == 0)
 +
{   
 +
    // Set all buttons in RCM_STRAPS and backup to PMC scratch
 +
    *(u32 *)APBDEV_PMC_SECURE_SCRATCH111_0 = (*(u32 *)APB_MISC_PP_STRAPPING_OPT_A_0 | 0x1C00);
 +
}
 +
else
 +
{
 +
    // Restore strapping options from PMC scratch
 +
    *(u32 *)APB_MISC_PP_STRAPPING_OPT_A_0 = *(u32 *)APBDEV_PMC_SECURE_SCRATCH111_0;
 +
}
 +
 
 +
// Disable write access to APBDEV_PMC_SECURE_SCRATCH111_0
 +
*(u32 *)APBDEV_PMC_SEC_DISABLE8_0 |= 0x4000;
 +
 +
return *(u32 *)APBDEV_PMC_SCRATCH0_0;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 5 ====
 +
This patch adjusts USB configurations.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 USB1_UTMIP_HSRX_CFG0_0 = 0x7D000810;
 +
u32 USB1_UTMIP_BIAS_CFG2_0 = 0x7D000850;
 +
 
 +
// Clear UTMIP_IDLE_WAIT, UTMIP_ELASTIC_LIMIT and UTMIP_PCOUNT_UPDN_DIV,
 +
// and set UTMIP_IDLE_WAIT to 0x11 and UTMIP_ELASTIC_LIMIT to 0x10
 +
*(u32 *)USB1_UTMIP_HSRX_CFG0_0 = ((*(u32 *)USB1_UTMIP_HSRX_CFG0_0 & ~(0xF8000) + 0x88000 & ~(0x7C00) + 0x4000) & ~(0xF000000));
 +
 +
// Clear UTMIP_HSSQUELCH_LEVEL_NEW
 +
*(u32 *)USB1_UTMIP_BIAS_CFG2_0 &= ~(0x07);
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 6 ====
 +
This patch is a factory backdoor.
 +
 
 +
It allows controlling the debug authentication configuration using a fuse.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 FUSE_ODM_INFO = 0x7000FA9C;
 +
 
 +
u32 odm_info = *(u32 *)FUSE_ODM_INFO;
 +
debug_auth_override_val = ((odm_info >> 0x08) << 0x01);
 +
 
 +
// Override debug authentication value stored in IRAM
 +
*(u32 *)0x400028E4 &= ~(debug_auth_override_val);
 +
 
 +
/*
 +
    Untranslated instructions:
 +
 +
    CMP    R0, #0
 +
*/
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 7 ====
 +
This patch is a bugfix.
 +
 
 +
It prevents overflowing IRAM (0x40010000) when copying the warmboot binary from DRAM.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 APBDEV_PMC_CNTRL_0 = 0x7000E400;
 +
 +
u32 warmboot_header_addr = 0x400049F0;
 +
u32 warmboot_bin_size = *(u32 *)warmboot_bin_header_addr;
 +
 +
// Invalid warmboot binary size
 +
if (warmboot_size >> 0x11)
 +
{
 +
    // Assert MAIN_RST
 +
    // 0x40004BF0 comes from R4 and the bootrom doesn't bother to change it
 +
    *(u32 *)APBDEV_PMC_CNTRL_0 = 0x40004BF0;
 +
 
 +
    // Deadlock
 +
    while(1);
 +
}
 +
 +
/*
 +
    Untranslated instructions:
 +
 +
    LDR    R0, =0x40010000
 +
    LDR    R2, [warmboot_bin_header_addr]
 +
*/
 +
 
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 8 ====
 +
This patch is a bugfix.
 +
 
 +
It sets the correct warmboot binary entrypoint address for RSA signature verification, which would be done in DRAM instead of IRAM without this patch.
 +
 
 +
<syntaxhighlight lang="c">
 +
u32 warmboot_addr_ptr = 0x40010238;
 +
u32 warmboot_entry_addr_ptr = 0x40004C28;
 +
 
 +
*(u32 *)warmboot_entry_addr_ptr = *(u32 *)warmboot_addr_ptr;
 +
 
 +
/*
 +
    Untranslated instructions:
 +
 +
    LDR    R2, [warmboot_addr_ptr]
 +
*/
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patches 9 and 10 ====
 +
These patches modify the 256-bit Secure Provisioning AES key with index 0x3A.
 +
 
 +
==== 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.
 +
 
 +
== Mariko ==
 +
{| class="wikitable" border="1"
 +
!  Name
 +
!  Number
 +
!  Redundant number
 +
!  Bits
 +
|-
 +
| enable_fuse_program
 +
| 0
 +
| 1
 +
| 0
 +
|-
 +
| disable_fuse_program
 +
| 0
 +
| 1
 +
| 1
 +
|-
 +
| bypass_fuses
 +
| 0
 +
| 1
 +
| 2
 +
|-
 +
| jtag_direct_access_disable
 +
| 0
 +
| 1
 +
| 3
 +
|-
 +
| production_mode
 +
| 0
 +
| 1
 +
| 4
 +
|-
 +
| jtag_secureid_valid
 +
| 0
 +
| 1
 +
| 5
 +
|-
 +
| odm_lock
 +
| 0
 +
| 1
 +
| 6-21
 +
|-
 +
| fa_mode
 +
| 0
 +
| 1
 +
| 22
 +
|-
 +
| security_mode
 +
| 0
 +
| 1
 +
| 23
 +
|-
 +
| arm_debug_dis
 +
| 0
 +
| 1
 +
| 24
 +
|-
 +
| obs_dis
 +
| 0
 +
| 1
 +
| 25
 +
|-
 +
| public_key0
 +
| 64
 +
| 65
 +
| 15-31
 +
|-
 +
| public_key0
 +
| 66
 +
| 67
 +
| 0-14
 +
|-
 +
| public_key1
 +
| 66
 +
| 67
 +
| 15-31
 +
|-
 +
| public_key1
 +
| 68
 +
| 69
 +
| 0-14
 +
|-
 +
| public_key2
 +
| 68
 +
| 69
 +
| 15-31
 +
|-
 +
| public_key2
 +
| 70
 +
| 71
 +
| 0-14
 +
|-
 +
| public_key3
 +
| 70
 +
| 71
 +
| 15-31
 +
|-
 +
| public_key3
 +
| 72
 +
| 73
 +
| 0-14
 +
|-
 +
| public_key4
 +
| 72
 +
| 73
 +
| 15-31
 +
|-
 +
| public_key4
 +
| 74
 +
| 75
 +
| 0-14
 +
|-
 +
| public_key5
 +
| 74
 +
| 75
 +
| 15-31
 +
|-
 +
| public_key5
 +
| 76
 +
| 77
 +
| 0-14
 +
|-
 +
| public_key6
 +
| 76
 +
| 77
 +
| 15-31
 +
|-
 +
| public_key6
 +
| 78
 +
| 79
 +
| 0-14
 +
|-
 +
| public_key7
 +
| 78
 +
| 79
 +
| 15-31
 +
|-
 +
| public_key7
 +
| 80
 +
| 81
 +
| 0-14
 +
|-
 +
| private_key0
 +
| 86
 +
| 87
 +
| 30-31
 +
|-
 +
| private_key0
 +
| 88
 +
| 89
 +
| 0-29
 +
|-
 +
| private_key1
 +
| 88
 +
| 89
 +
| 30-31
 +
|-
 +
| private_key1
 +
| 90
 +
| 91
 +
| 0-29
 +
|-
 +
| private_key2
 +
| 90
 +
| 91
 +
| 30-31
 +
|-
 +
| private_key2
 +
| 92
 +
| 93
 +
| 0-29
 +
|-
 +
| private_key3
 +
| 92
 +
| 93
 +
| 30-31
 +
|-
 +
| private_key3
 +
| 94
 +
| 95
 +
| 0-29
 +
|-
 +
| private_key4
 +
| 94
 +
| 95
 +
| 30-31
 +
|-
 +
| private_key4
 +
| 96
 +
| 97
 +
| 0-29
 +
|-
 +
| boot_device_info
 +
| 96
 +
| 97
 +
| 30-31
 +
|-
 +
| boot_device_info
 +
| 98
 +
| 99
 +
| 0-13
 +
|-
 +
| reserved_sw
 +
| 98
 +
| 99
 +
| 14-25
 +
|-
 +
| secure_provision_index
 +
| 152
 +
| 153
 +
| 23-26
 +
|-
 +
| secure_provision_info
 +
| 152
 +
| 153
 +
| 27-28
 +
|-
 +
| aid
 +
| 165
 +
| None
 +
| 2-31
 +
|-
 +
| aid
 +
| 166
 +
| None
 +
| 0-1
 +
|-
 +
| spare_bit_0
 +
| 167
 +
| None
 +
| 2
 +
|-
 +
| spare_bit_1
 +
| 167
 +
| None
 +
| 3
 +
|-
 +
| spare_bit_2
 +
| 167
 +
| None
 +
| 4
 +
|-
 +
| spare_bit_3
 +
| 167
 +
| None
 +
| 5
 +
|-
 +
| spare_bit_4
 +
| 167
 +
| None
 +
| 6
 +
|-
 +
| spare_bit_5
 +
| 167
 +
| None
 +
| 7
 +
|-
 +
| spare_bit_6
 +
| 167
 +
| None
 +
| 8
 +
|-
 +
| spare_bit_7
 +
| 167
 +
| None
 +
| 9
 +
|-
 +
| spare_bit_8
 +
| 167
 +
| None
 +
| 10
 +
|-
 +
| spare_bit_9
 +
| 167
 +
| None
 +
| 11
 +
|-
 +
| spare_bit_10
 +
| 167
 +
| None
 +
| 12
 +
|-
 +
| spare_bit_11
 +
| 167
 +
| None
 +
| 13
 +
|-
 +
| spare_bit_12
 +
| 167
 +
| None
 +
| 14
 +
|-
 +
| spare_bit_13
 +
| 167
 +
| None
 +
| 15
 +
|-
 +
| spare_bit_14
 +
| 167
 +
| None
 +
| 16
 +
|-
 +
| spare_bit_15
 +
| 167
 +
| None
 +
| 17
 +
|-
 +
| spare_bit_16
 +
| 167
 +
| None
 +
| 18
 +
|-
 +
| spare_bit_17
 +
| 167
 +
| None
 +
| 19
 +
|-
 +
| spare_bit_18
 +
| 167
 +
| None
 +
| 20
 +
|-
 +
| spare_bit_19
 +
| 167
 +
| None
 +
| 21
 +
|-
 +
| spare_bit_20
 +
| 167
 +
| None
 +
| 22
 +
|-
 +
| spare_bit_21
 +
| 167
 +
| None
 +
| 23
 +
|-
 +
| spare_bit_22
 +
| 167
 +
| None
 +
| 24
 +
|-
 +
| spare_bit_23
 +
| 167
 +
| None
 +
| 25
 +
|-
 +
| spare_bit_24
 +
| 167
 +
| None
 +
| 26
 +
|-
 +
| spare_bit_25
 +
| 167
 +
| None
 +
| 27
 +
|-
 +
| spare_bit_26
 +
| 167
 +
| None
 +
| 28
 +
|-
 +
| spare_bit_27
 +
| 167
 +
| None
 +
| 29
 +
|-
 +
| spare_bit_28
 +
| 167
 +
| None
 +
| 30
 +
|-
 +
| spare_bit_29
 +
| 167
 +
| None
 +
| 31
 +
|-
 +
| reshift_fcpu0
 +
| 168
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu1
 +
| 169
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu2
 +
| 170
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fcpu3
 +
| 171
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank0
 +
| 172
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank1
 +
| 173
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank2
 +
| 174
 +
| None
 +
| 0-31
 +
|-
 +
| reshift_fl2_tbank3
 +
| 175
 +
| None
 +
| 0-31
 +
|-
 +
| [[#irom_patch_2|irom_patch]]
 +
| 176
 +
| None
 +
| Variable
 +
|}
 +
 
 +
=== irom_patch ===
 +
<syntaxhighlight>
 +
RAM:00000000 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000000
 +
RAM:00000000
 +
RAM:00000000 irom_svc_dispatch
 +
RAM:00000000  STMFD  SP!, {R0-R2}                  ; ipatches:
 +
RAM:00000000                                        ;  0: 0x085bdf00 0x001010b6 0x0000df00 : svc #0x00 (offset 0x48)
 +
RAM:00000000                                        ;
 +
RAM:00000000                                        ;  0: 0x12d3df06 0x001025a6 0x0000df06 : svc #0x06 (offset 0x54)
 +
RAM:00000000                                        ;  1: 0x28144770 0x00105028 0x00004770 : bx lr
 +
RAM:00000000                                        ;  2: 0x0fb72001 0x00101f6e 0x00002001 : movs r0, #0x01
 +
RAM:00000000                                        ;  3: 0x692ddf15 0x0010d25a 0x0000df15 : svc #0x15 (offset 0x72)
 +
RAM:00000000                                        ;  4: 0x436ddf1f 0x001086da 0x0000df1f : svc #0x1f (offset 0x86)
 +
RAM:00000000                                        ;  5: 0x4376df23 0x001086ec 0x0000df23 : svc #0x23 (offset 0x8e)
 +
RAM:00000000                                        ;  6: 0x4103df2b 0x00108206 0x0000df2b : svc #0x2b (offset 0x9e)
 +
RAM:00000000                                        ;  7: 0x495c0060 0x001092b8 0x00000060 : lsls r0, r4, #1
 +
RAM:00000000                                        ;  8: 0x62e3ef5b 0x0010c5c6 0x0000ef5b
 +
RAM:00000000                                        ;  9: 0x10d1df6a 0x001021a2 0x0000df6a : svc #0x6a (offset 0x11c)
 +
RAM:00000004  MOV    R2, LR
 +
RAM:00000008  SUB    R2, R2, #2
 +
RAM:0000000C  LDR    R2, [R2]
 +
RAM:00000010  AND    R2, R2, #0xFF
 +
RAM:00000014  MOV    R2, R2,LSL#1
 +
RAM:00000018  LDR    R0, =0x10022C
 +
RAM:0000001C  LDR    R1, =0x100174
 +
RAM:00000020  SUB    R1, R1, R0
 +
RAM:00000024  LDR    R0, =0x40004164
 +
RAM:00000028  ADD    R0, R0, R1
 +
RAM:0000002C  ADD    R2, R2, R0
 +
RAM:00000030  ORR    R2, R2, #1
 +
RAM:00000034  LDMFD  SP!, {R0,R1}
 +
RAM:00000038  BX      R2
 +
RAM:00000038 ; End of function irom_svc_dispatch
 +
RAM:00000038
 +
RAM:00000038 ; ---------------------------------------------------------------------------
 +
RAM:0000003C dword_3C        DCD 0x10022C            ; DATA XREF: irom_svc_dispatch+18↑r
 +
RAM:00000040 dword_40        DCD 0x100174            ; DATA XREF: irom_svc_dispatch+1C↑r
 +
RAM:00000044 dword_44        DCD 0x40004164          ; DATA XREF: irom_svc_dispatch+24↑r
 +
RAM:00000048  CODE16
 +
RAM:00000048
 +
RAM:00000048 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000048
 +
RAM:00000048
 +
RAM:00000048 sub_48                                  ; 0: 0x085bdf00 0x001010b6 0x0000df00 : svc #0x00 (offset 0x48)
 +
RAM:00000048  CMP    R5, #0xAF
 +
RAM:0000004A  BNE    loc_4E
 +
RAM:0000004C  MOVS    R5, #0xFF
 +
RAM:0000004E
 +
RAM:0000004E loc_4E                                  ; CODE XREF: sub_48+2↑j
 +
RAM:0000004E  SUBS    R6, R5, #1
 +
RAM:00000050
 +
RAM:00000050 loc_50                                  ; CODE XREF: sub_54+18↓j
 +
RAM:00000050                                        ; sub_72+12↓j ...
 +
RAM:00000050  POP    {R2}
 +
RAM:00000052  MOV    PC, LR
 +
RAM:00000052 ; End of function sub_48
 +
RAM:00000052
 +
RAM:00000054
 +
RAM:00000054 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000054
 +
RAM:00000054
 +
RAM:00000054 sub_54                                  ; 0: 0x12d3df06 0x001025a6 0x0000df06 : svc #0x06 (offset 0x54)
 +
RAM:00000054  MOVS    R3, #7
 +
RAM:00000056
 +
RAM:00000056 loc_56                                  ; CODE XREF: sub_72+10↓j
 +
RAM:00000056                                        ; sub_8E+E↓j
 +
RAM:00000056  PUSH    {R0,R1,R3-R6}
 +
RAM:00000058  LDR    R0, =0x4000FC20
 +
RAM:0000005A  LDR    R1, =0x40040000
 +
RAM:0000005C  LDR    R3, =0xEAFFFFFE
 +
RAM:0000005E  MOVS    R4, R3
 +
RAM:00000060  MOVS    R5, R3
 +
RAM:00000062  ADDS    R6, R3, #0
 +
RAM:00000064
 +
RAM:00000064 loc_64                                  ; CODE XREF: sub_54+14↓j
 +
RAM:00000064  STMIA  R0!, {R3-R6}
 +
RAM:00000066  CMP    R0, R1
 +
RAM:00000068  BCC    loc_64
 +
RAM:0000006A  POP    {R0,R1,R3-R6}
 +
RAM:0000006C  B      loc_50
 +
RAM:0000006C ; End of function sub_54
 +
RAM:0000006C
 +
RAM:0000006E ; ---------------------------------------------------------------------------
 +
RAM:0000006E ; START OF FUNCTION CHUNK FOR sub_8E
 +
RAM:0000006E
 +
RAM:0000006E loc_6E                                  ; CODE XREF: sub_8E+8↓j
 +
RAM:0000006E  LDR    R0, =0x1002A0
 +
RAM:00000070  BX      R0
 +
RAM:00000070 ; END OF FUNCTION CHUNK FOR sub_8E
 +
RAM:00000072
 +
RAM:00000072 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000072
 +
RAM:00000072
 +
RAM:00000072 sub_72                                  ; 3: 0x692ddf15 0x0010d25a 0x0000df15 : svc #0x15 (offset 0x72)
 +
RAM:00000072  MOVS    R2, #2
 +
RAM:00000074  CMP    R0, #0x26 ; '&'
 +
RAM:00000076  BLS    loc_7A
 +
RAM:00000078  ADDS    R2, #0x50 ; 'P'
 +
RAM:0000007A
 +
RAM:0000007A loc_7A                                  ; CODE XREF: sub_72+4↑j
 +
RAM:0000007A  MOV    R3, LR
 +
RAM:0000007C  ADDS    R3, R3, R2
 +
RAM:0000007E  MOV    LR, R3
 +
RAM:00000080  CMP    R0, #0
 +
RAM:00000082  BNE    loc_56
 +
RAM:00000084  B      loc_50
 +
RAM:00000084 ; End of function sub_72
 +
RAM:00000084
 +
RAM:00000086
 +
RAM:00000086 ; =============== S U B R O U T I N E =======================================
 +
RAM:00000086
 +
RAM:00000086
 +
RAM:00000086 sub_86                                  ; 4: 0x436ddf1f 0x001086da 0x0000df1f : svc #0x1f (offset 0x86)
 +
RAM:00000086
 +
RAM:00000086 arg_8  =  8
 +
RAM:00000086
 +
RAM:00000086  MOVS    R3, R0
 +
RAM:00000088  LDR    R2, =0x5A55F0E1
 +
RAM:0000008A  STR    R2, [SP,#arg_8]
 +
RAM:0000008C  B      loc_50
 +
RAM:0000008C ; End of function sub_86
 +
RAM:0000008C
 +
RAM:0000008E
 +
RAM:0000008E ; =============== S U B R O U T I N E =======================================
 +
RAM:0000008E
 +
RAM:0000008E
 +
RAM:0000008E sub_8E                                  ; 5: 0x4376df23 0x001086ec 0x0000df23 : svc #0x23 (offset 0x8e)
 +
RAM:0000008E
 +
RAM:0000008E arg_8  =  8
 +
RAM:0000008E
 +
RAM:0000008E ; FUNCTION CHUNK AT RAM:0000006E SIZE 00000004 BYTES
 +
RAM:0000008E
 +
RAM:0000008E  MOVS    R3, R0
 +
RAM:00000090  LDR    R2, =0x5A55F0E1
 +
RAM:00000092  LDR    R0, [SP,#arg_8]
 +
RAM:00000094  CMP    R0, R2
 +
RAM:00000096  BEQ    loc_6E
 +
RAM:00000098  CMP    R0, #0
 +
RAM:0000009A  BEQ    loc_50
 +
RAM:0000009C  B      loc_56
 +
RAM:0000009C ; End of function sub_8E
 +
RAM:0000009C
 +
RAM:0000009E
 +
RAM:0000009E ; =============== S U B R O U T I N E =======================================
 +
RAM:0000009E
 +
RAM:0000009E
 +
RAM:0000009E sub_9E                                  ; 6: 0x4103df2b 0x00108206 0x0000df2b : svc #0x2b (offset 0x9e)
 +
RAM:0000009E  LDR    R0, =0x7000F900
 +
RAM:000000A0  SUBS    R0, #0xD8
 +
RAM:000000A2  MOVS    R2, #1
 +
RAM:000000A4  STR    R2, [R0]
 +
RAM:000000A6  LDR    R0, =0x7001231C
 +
RAM:000000A8  LDR    R3, =0x7041231C
 +
RAM:000000AA  MOVS    R1, #0xE0
 +
RAM:000000AC  B      loc_B4
 +
RAM:000000AE ; ---------------------------------------------------------------------------
 +
RAM:000000AE
 +
RAM:000000AE loc_AE                                  ; CODE XREF: sub_9E+2E↓j
 +
RAM:000000AE  MOVS    R1, #0xF0
 +
RAM:000000B0  B      loc_B4
 +
RAM:000000B2 ; ---------------------------------------------------------------------------
 +
RAM:000000B2
 +
RAM:000000B2 loc_B2                                  ; CODE XREF: sub_9E+32↓j
 +
RAM:000000B2  MOVS    R1, #0xC0
 +
RAM:000000B4
 +
RAM:000000B4 loc_B4                                  ; CODE XREF: sub_9E+E↑j
 +
RAM:000000B4                                        ; sub_9E+12↑j
 +
RAM:000000B4  MOVS    R4, #0
 +
RAM:000000B6
 +
RAM:000000B6 loc_B6                                  ; CODE XREF: sub_9E+28↓j
 +
RAM:000000B6  MOVS    R2, #0
 +
RAM:000000B8  STR    R1, [R0]
 +
RAM:000000BA  STR    R2, [R0,#4]
 +
RAM:000000BC  STR    R1, [R3]
 +
RAM:000000BE  STR    R2, [R3,#4]
 +
RAM:000000C0  ADDS    R1, #1
 +
RAM:000000C2  ADDS    R4, #1
 +
RAM:000000C4  CMP    R4, #7
 +
RAM:000000C6  BLS    loc_B6
 +
RAM:000000C8  LSRS    R1, R1, #4
 +
RAM:000000CA  CMP    R1, #0xE
 +
RAM:000000CC  BEQ    loc_AE
 +
RAM:000000CE  CMP    R1, #0xF
 +
RAM:000000D0  BEQ    loc_B2
 +
RAM:000000D2  MOV    R5, LR
 +
RAM:000000D4  MOVS    R0, #0
 +
RAM:000000D6
 +
RAM:000000D6 loc_D6                                  ; CODE XREF: sub_9E+56↓j
 +
RAM:000000D6  MOVS    R1, #0xD
 +
RAM:000000D8  MOVS    R2, #0
 +
RAM:000000DA  MOVS    R3, #0xD
 +
RAM:000000DC  PUSH    {R0-R3}
 +
RAM:000000DE  LDR    R4, =0x40004164
 +
RAM:000000E0  PUSH    {R2,R4}
 +
RAM:000000E2  ADRL    R4, (loc_EC+1)
 +
RAM:000000E6  MOV    LR, R4
 +
RAM:000000E8  LDR    R4, =0x105A19
 +
RAM:000000EA  BX      R4
 +
RAM:000000EC
 +
RAM:000000EC loc_EC                                  ; DATA XREF: sub_9E+44↑o
 +
RAM:000000EC  ADD    SP, SP, #8
 +
RAM:000000EE  POP    {R0-R3}
 +
RAM:000000F0  ADDS    R0, #1
 +
RAM:000000F2  CMP    R0, #1
 +
RAM:000000F4  BEQ    loc_D6
 +
RAM:000000F6  MOV    LR, R5
 +
RAM:000000F8  LDR    R0, =0x4000FC20
 +
RAM:000000FA  MOV    R8, R0
 +
RAM:000000FC  B      loc_50
 +
RAM:000000FC ; End of function sub_9E
 +
RAM:000000FC
 +
RAM:000000FE
 +
RAM:000000FE ; =============== S U B R O U T I N E =======================================
 +
RAM:000000FE
 +
RAM:000000FE
 +
RAM:000000FE sub_FE
 +
RAM:000000FE  POP    {R2}
 +
RAM:00000100  MOV    R4, SP
 +
RAM:00000102  SUBS    R4, R4, R0
 +
RAM:00000104  BLS    loc_10C
 +
RAM:00000106  CMP    R4, R2
 +
RAM:00000108  BCS    loc_118
 +
RAM:0000010A  B      loc_116
 +
RAM:0000010C ; ---------------------------------------------------------------------------
 +
RAM:0000010C
 +
RAM:0000010C loc_10C                                ; CODE XREF: sub_FE+6↑j
 +
RAM:0000010C  LDR    R4, =0x4000BE68
 +
RAM:0000010E  SUBS    R4, R4, R0
 +
RAM:00000110  BLS    loc_118
 +
RAM:00000112  CMP    R4, R2
 +
RAM:00000114  BCS    loc_118
 +
RAM:00000116
 +
RAM:00000116 loc_116                                ; CODE XREF: sub_FE+C↑j
 +
RAM:00000116  ADDS    R2, R4, #0
 +
RAM:00000118
 +
RAM:00000118 loc_118                                ; CODE XREF: sub_FE+A↑j
 +
RAM:00000118                                        ; sub_FE+12↑j ...
 +
RAM:00000118  SUBS    R3, R0, R1
 +
RAM:0000011A  BX      LR
 +
RAM:0000011A ; End of function sub_FE
 +
RAM:0000011A
 +
RAM:0000011C
 +
RAM:0000011C ; =============== S U B R O U T I N E =======================================
 +
RAM:0000011C
 +
RAM:0000011C
 +
RAM:0000011C sub_11C                                ; 9: 0x10d1df6a 0x001021a2 0x0000df6a : svc #0x6a (offset 0x11c)
 +
RAM:0000011C  SUBS    R3, #5
 +
RAM:0000011E  MOVS    R2, #0xF0
 +
RAM:00000120  BICS    R2, R3
 +
RAM:00000122  B      loc_50
 +
RAM:00000122 ; End of function sub_11C
 +
RAM:00000122
 +
RAM:00000122 ; ---------------------------------------------------------------------------
 +
RAM:00000124 dword_124      DCD 0x4000FC20          ; DATA XREF: sub_54+4↑r
 +
RAM:00000124                                        ; sub_9E+5A↑r
 +
RAM:00000128 dword_128      DCD 0x40040000          ; DATA XREF: sub_54+6↑r
 +
RAM:0000012C dword_12C      DCD 0xEAFFFFFE          ; DATA XREF: sub_54+8↑r
 +
RAM:00000130 off_130        DCD 0x1002A0            ; DATA XREF: sub_8E:loc_6E↑r
 +
RAM:00000134 dword_134      DCD 0x5A55F0E1          ; DATA XREF: sub_86+2↑r
 +
RAM:00000134                                        ; sub_8E+2↑r
 +
RAM:00000138 dword_138      DCD 0x7000F900          ; DATA XREF: sub_9E↑r
 +
RAM:0000013C off_13C        DCD 0x7001231C          ; DATA XREF: sub_9E+8↑r
 +
RAM:00000140 off_140        DCD 0x7041231C          ; DATA XREF: sub_9E+A↑r
 +
RAM:00000144 dword_144      DCD 0x40004164          ; DATA XREF: sub_9E+40↑r
 +
RAM:00000148 off_148        DCD 0x105A19            ; DATA XREF: sub_9E+4A↑r
 +
RAM:0000014C dword_14C      DCD 0x4000BE68          ; DATA XREF: sub_FE:loc_10C↑r
 +
RAM:0000014C ; RAM          ends
 +
</syntaxhighlight>
 +
 
 +
==== First IROM patch ====
 +
This patch is applied to the bootrom IPATCH handling function so that more patches can be loaded from fuses.
 +
 
 +
<syntaxhighlight lang="c">
 +
if (patch_start_addr == 0xAF) {
 +
    patch_start_addr = 0xFF;
 +
}
 +
 +
patch_start_addr--;
 +
 +
return;
 +
</syntaxhighlight>
 +
 
 +
==== IROM patch 0 ====
 +
This patch initializes all unused IRAM memory to 0xEAFFFFFE (infinite loop instruction).
 +
 
 +
<syntaxhighlight lang="c">
 +
/*
 +
    Untranslated instructions:
 +
 +
    MOVS    R3, #7
 +
    PUSH    {R0,R1,R3-R6}
 +
*/
 +
 +
for (u32 addr = 0x4000FC20; addr < 0x40040000; addr += 0x04) {
 +
    *(u32 *)addr = 0xEAFFFFFE;
 +
}
 +
 +
/*
 +
    Untranslated instructions:
 +
 +
    POP    {R0,R1,R3-R6}
 +
  */
 +
   
 +
  return;
 +
</syntaxhighlight>
 +
 
 +
= Anti-downgrade =
 +
The first bootloader verifies [[#FUSE_RESERVED_ODM7|FUSE_RESERVED_ODM7]] to prevent downgrading.
 +
How many fuses are expected to be burnt depends the device's unit type as below.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! System version
 +
! Expected number of burnt fuses (retail)
 
! Expected number of burnt fuses (non-retail)
 
! Expected number of burnt fuses (non-retail)
 
|-
 
|-
Line 2,279: Line 3,644:  
| 1
 
| 1
 
|-
 
|-
| 9.1.0
+
| 9.1.0-9.2.0
 
| 12
 
| 12
 +
| 1
 +
|-
 +
| 10.0.0-10.0.4
 +
| 13
 
| 1
 
| 1
 
|}
 
|}

Navigation menu