Changes

5,764 bytes added ,  18:33, 24 April 2018
documenting ipatches
Line 88: Line 88:  
==== FUSE_WRITE_ACCESS ====
 
==== FUSE_WRITE_ACCESS ====
 
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.
      
=== Cache registers ===
 
=== Cache registers ===
Line 575: Line 574:     
=== bootrom_ipatch ===
 
=== bootrom_ipatch ===
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 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. The revision stored in FUSE_CP_REV indicates the unique set of values stored in ipatch fuses.
 
  −
The revision stored in FUSE_CP_REV indicates the unique set of values stored in ipatch fuses.
      
The following represents the patch data dumped from a Switch console:
 
The following represents the patch data dumped from a Switch console:
Line 815: Line 812:     
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 ====
 +
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>
 +
 +
==== ipatch 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>
 +
 +
==== ipatch 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>
 +
 +
==== ipatch 3 ====
 +
This patch pertains to XHCI IRQ clearing checks and forces a result code to be 0.
 +
 +
==== ipatch 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>
 +
 +
==== ipatch 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>
 +
 +
==== ipatch 6 ====
 +
This patch is a factory backdoor.
 +
 +
It allows controlling the debug authentication configuration using a fuse.
 +
 +
<syntaxhighlight lang="c">
 +
u32 FUSE_DEBUG_AUTH_OVERRIDE = 0x7000FA9C;
 +
 +
u32 debug_auth_override_val = *(u32 *)FUSE_DEBUG_AUTH_OVERRIDE;
 +
debug_auth_override_val = ((debug_auth_override_val >> 0x08) << 0x01);
 +
 +
// Override debug authentication value stored in IRAM
 +
*(u32 *)0x400028E4 &= ~(debug_auth_override_val);
 +
 +
/*
 +
    Untranslated instructions:
 +
 +
    CMP    R0, #0
 +
*/
 +
 +
return;
 +
</syntaxhighlight>
 +
 +
==== ipatch 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>
 +
 +
==== ipatch 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>
 +
 +
==== ipatches 9 and 10 ====
 +
These patches modify the 256-bit Secure Provisioning AES key with index 0x3A.
 +
 +
==== ipatch 11 ====
 +
This patch pertains to the [[Security_Engine|Security Engine]] context restore process and forces SE_OPERATION_UNK1 to be 0x01.
    
== Anti-downgrade ==
 
== Anti-downgrade ==