Burning Fuse to Enable USB3 SS Recovery Mode

I’m trying to follow the instructions from Enabling AGX Orin, Orin NX, and Orin Nano in USB3 Recovery Mode but I don’t have the suggested Factory Secure Key Provisioning tool. It is no where to be found and our Arrow Electronics / NVIDIA contact is asking for public cert for signing but there’s a misunderstanding. To my understanding we just need to set bit 7 of FUSE_RESERVED_SW_0 and whatever else is required to work with it (bits 8 and 11 of BootDevInfo or FUSE_BOOT_DEVICE_INFO_0?).

We are not looking to burn any other fuses and do not want to lock down the AGX with any encryption. So far I’ve tried reading and writing to a devkit using the included odmfuseread.sh and odmfuse.sh scripts included with JP 36.4.

I’ve modified the odmfuse.func to also read BootDevInfo by adding it to line 58:

FUSES_MANUFACTURING_T234=("BootSecurityInfo" "ArmJtagDisable" "SecurityMode" "SwReserve     d" "DebugAuthentication" "OdmId" "BootDevInfo");

Reading the fresh module shows:

Fuse reading is done. The fuse values have been saved in: /home/acs/git/turret-vision/jetson_flashing/bf_motherboard_v2/Linux_for_Tegra/bootloader/fuse_info.txt
PublicKeyHash: 34faf07ef705737b635f8518fb937240468135e78ba6971689ce2f5b5b1a8e62263bce8e8a484e6c25a10d05b0a9e5d003614bf2543ce490c002845585efa164
BootSecurityInfo: 000001e0
ArmJtagDisable: 00000000
SecurityMode: 00000000
SwReserved: 00000000
DebugAuthentication: 00000000
OdmId: 0000000000000000
BootDevInfo: 00000000
OdmLock: 00000000
ReservedOdm0: 00000000
ReservedOdm1: 00000000
ReservedOdm2: 00000000
ReservedOdm3: 00000000
ReservedOdm4: 00000000
ReservedOdm5: 00000000
ReservedOdm6: 00000000
ReservedOdm7: 00000000

I then tried to burn the module with sudo ./odmfuse.sh -i 0x23 -r 0x80 jetson-agx-orin-devkit and host showed it completed successfully. I did not capture the AGX UART log from it at the time.

However, running the same read command as above to read back the fuses shows SwReserved: 00000008 instead of exectedSwReserved: 00000080

Trying to rerun the same write command shows this on the host:

(standard_in) 1: syntax error
SwReserved: you can't reset bits from 1 to 0. You're changing 0x8 to 0x80.

I then tried to write again but with the overlapping bit set using sudo ./odmfuse.sh -i 0x23 -r 0x88 jetson-agx-orin-devkit:

[0007.885] I> Task: Disable SCPM/POD reset
[0007.889] I> SLCG Global override status := 0x0
[0007.894] I> MB1: MSS reconfig completed
I> FSKP (version: 0.0.0.0-t234-54845784-33c9168e)
I> t234-A01-1-Silicon (0x12347)
I> Emulation:
I> Entry timestamp: 0x0078e96b
I> Regular heap: [base:0x40040000, size:0x10000]
I> DMA heap: [base:0x102e000000, size:0x800000]
I> Task: Crypto init
I> Task: Program CBB PCIE AMAP regions
I> Task: Burn fuses
I> Index : 1    SwReserved    size: 4
I> Fuse Blob found
I>
I> Burning fuses
I> 1. Start SwReserved burn
E> FUSE: Failed to burn fuse addr: 0xc5.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Failed burn fuses as per fuse info.
E> FSKP: Failed to burn fuses.
C> Task 0x0 failed (err: 0x62170302)
E> Top caller module: FSKP, error module: FUSE, reason: 0x02, aux_info: 0x03
I> Busy Spin

hello joseph.gao,

let me have confirmation, it’s odmfuseread.sh to read the fuse value,
please refer to developer guide, Burn Fuses with the Fuse Configuration file.
for fuse burn, you should execute odmfuse.sh instead.
for instance, $ sudo ./odmfuse.sh -X <fuse_config> -i <chip_id> <target_config>

please also refer to Jetson Orin Series Modules Fuse Update Field Services Bulletin.
the fuse value for boot_security_info was burned (by manufacturing) to 0x1E0.
you must do bitwise logically OR with 0x1E0 in their fuse programming flow.
you may have fuse.xml as below per your use-case, since you’re programming SwReserved only.
for instance,

<genericfuse MagicId="0x45535546" version="1.0.0">
   <fuse name="BootSecurityInfo" size="4" value="0x1e0"/>
   <fuse name="SwReserved" size="4" value="0xXXX"/>
</genericfuse>

BTW, please see-also similar forum Topic 342679 to program FUSE_RESERVED_SW_0.

Hi Jerry, thank you for the prompt response.

Sorry for the typo, the I did use odmfuse.sh to burn the fuse, and odmfuseread.sh to read. Both the following are ran with odmfuse.sh and NOT odmfuseread.sh

I will edit the original post for clarification.

I am trying to only target the SwReserved fuse and not BootSecurityInfo, as per odmfuse.sh’s -h output:

 -r <0xXX> ---------------- sets sw_reserved=0xXX.

I have also tried burning it with the usb3.xml provided in the section from:

which is:

<genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="BootDevInfo" size="4" value="0x00000900"/>
        <fuse name="SwReserved" size="4" value="0x00000080"/>
</genericfuse>

and I after editing it to include the already burned fuses as per the bulletin provided and what I read out previously as well as the incorrectly burned bit 3 of SwReserved, I have:

<genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="BootDevInfo" size="4" value="0x000001E0"/>
        <fuse name="SwReserved" size="4" value="0x00000088"/>
</genericfuse>

After running $ sudo ./odmfuse.sh -i 0x23 -X usb3.xml jetson-agx-orin-devkit | tee ~/devkit_fuse_write_host.log, I see this still in UART console:

[0008.309] I> MB1: MSS reconfig completed
I> FSKP (version: 0.0.0.0-t234-54845784-33c9168e)
I> t234-A01-1-Silicon (0x12347)
I> Emulation:
I> Entry timestamp: 0x007f3206
I> Regular heap: [base:0x40040000, size:0x10000]
I> DMA heap: [base:0x102e000000, size:0x800000]
I> Task: Crypto init
I> Task: Program CBB PCIE AMAP regions
I> Task: Burn fuses
I> Index : 1    BootDevInfo    size: 4
I> Index : 2    SwReserved    size: 4
I> Fuse Blob found
I>
I> Burning fuses
I> 1. Start BootDevInfo burn
I> 1. BootDevInfo burnt successfully
W> No handling of CRC-32 for BootDevInfo
I>
I> 2. Start SwReserved burn
E> FUSE: Failed to burn fuse addr: 0xc5.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Failed burn fuses as per fuse info.
E> FSKP: Failed to burn fuses.
C> Task 0x0 failed (err: 0x62170302)
E> Top caller module: FSKP, error module: FUSE, reason: 0x02, aux_info: 0x03
I> Busy Spin

The full target AGX UART log and host log is attached here.
devkit_fuse_write_target.log (15.4 KB)
devkit_fuse_write_host.log (98.9 KB)

@JerryChang Please advise.

hello joseph.gao,

you should have BootSecurityInfo which as same as default value, 0x1e0 within fuse xml file.

Hi @JerryChang,

I’ve tried that as well but the UART log output is identical. ‘BootSecurityInfo’ claims to be written successfully but ‘SwReserved’ fails the same. Upon reading back fuse values after write, I see ‘BootSecurityInfo’ is still stuck at 0x1E0

hello joseph.gao,

I doubt the fuse processing has abort due to key mismatched.
please check odmfuseread again, let’s check what’s your current fuse variable returns.

Hi @JerryChang,

Here’s the read back with sudo ./odmfuseread.sh -i 0x23 jetson-agx-orin-devkit | tee ~/devkit_fuse_write_host.log:

Fuse reading is done. The fuse values have been saved in: /home/acs/git/turret-vision/jetson_flashing/bf_motherboard_v2/Linux_for_Tegra/bootloader/fuse_info.txt
PublicKeyHash: 34faf07ef705737b635f8518fb937240468135e78ba6971689ce2f5b5b1a8e62263bce8e8a484e6c25a10d05b0a9e5d003614bf2543ce490c002845585efa164
BootSecurityInfo: 000001e0
ArmJtagDisable: 00000000
SecurityMode: 00000000
SwReserved: 00000008
DebugAuthentication: 00000000
OdmId: 0000000000000000
BootDevInfo: 000001e0
OdmLock: 00000000
ReservedOdm0: 00000000
ReservedOdm1: 00000000
ReservedOdm2: 00000000
ReservedOdm3: 00000000
ReservedOdm4: 00000000
ReservedOdm5: 00000000
ReservedOdm6: 00000000
ReservedOdm7: 00000000

Full log here:
devkit_fuse_write_host.log (53.6 KB)

I see I had confused BootSecurityInfo and BootDevInfo previously, so now they’re both written as 0x1e0 on this sacrificial AGX module.

I’ve added this to my usb3.xml file, and updated BootDevInfo to set bit 11 as specified in the guide:

<genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="BootDevInfo" size="4" value="0x000009E0"/>
        <fuse name="BootSecurityInfo" size="4" value="0x000001E0"/>
        <fuse name="SwReserved" size="4" value="0x00000088"/>
</genericfuse>

and after running sudo ./odmfuse.sh -i 0x23 -X usb3.xml jetson-agx-orin-devkit | tee ~/devkit_fuse_write_host.log to burn again, the host reports complete and UART console shows BootDevInfo and BootSecurityInfo are written successfully, but SwReserved still fails:

[0007.997] I> MB1: MSS reconfig completed
I> FSKP (version: 0.0.0.0-t234-54845784-33c9168e)
I> t234-A01-1-Silicon (0x12347)
I> Emulation:
I> Entry timestamp: 0x007a71a1
I> Regular heap: [base:0x40040000, size:0x10000]
I> DMA heap: [base:0x102e000000, size:0x800000]
I> Task: Crypto init
I> Task: Program CBB PCIE AMAP regions
I> Task: Burn fuses
I> Index : 1    BootDevInfo    size: 4
I> Index : 2    BootSecurityInfo    size: 4
I> Index : 3    SwReserved    size: 4
I> Fuse Blob found
I>
I> Burning fuses
I> 1. Start BootDevInfo burn
I> 1. BootDevInfo burnt successfully
W> No handling of CRC-32 for BootDevInfo
I>
I> 2. Start BootSecurityInfo burn
I> Fuse is already burned with the same value
I> 2. BootSecurityInfo burn skipped
I>
I> 3. Start SwReserved burn
E> FUSE: Failed to burn fuse addr: 0xc5.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Failed burn fuses as per fuse info.
E> FSKP: Failed to burn fuses.
C> Task 0x0 failed (err: 0x62170302)
E> Top caller module: FSKP, error module: FUSE, reason: 0x02, aux_info: 0x03
I> Busy Spin

Here’s the full target UART log:
devkit_fuse_write_target.log (15.5 KB)

Once again, reading back the fuse values shows the same:

Fuse reading is done. The fuse values have been saved in: /home/acs/git/turret-vision/jetson_flashing/bf_motherboard_v2/Linux_for_Tegra/bootloader/fuse_info.txt
PublicKeyHash: 34faf07ef705737b635f8518fb937240468135e78ba6971689ce2f5b5b1a8e62263bce8e8a484e6c25a10d05b0a9e5d003614bf2543ce490c002845585efa164
BootSecurityInfo: 000001e0
ArmJtagDisable: 00000000
SecurityMode: 00000000
SwReserved: 00000008
DebugAuthentication: 00000000
OdmId: 0000000000000000
BootDevInfo: 000001e0
OdmLock: 00000000
ReservedOdm0: 00000000
ReservedOdm1: 00000000
ReservedOdm2: 00000000
ReservedOdm3: 00000000
ReservedOdm4: 00000000
ReservedOdm5: 00000000
ReservedOdm6: 00000000
ReservedOdm7: 00000000

@JerryChang Please advise, I am at your mercy

hello joseph.gao,

just for confirmation, you’ve fused a PKC key?

Hi @JerryChang

I have not before, but the previous history of this AGX is dubious. However, the same results are replicated on a different AGX module without PKC key written.

PKC being burned shouldn’t affect the ability to burn the other fuses as long as secure mode bit is not burned right?

hello joseph.gao,

it’s Bits [2:0] in FUSE_BOOT_SECURITY_INFO_0 of Secure Boot Authentication Scheme
please refer to Jetson Orin Fuse Specification.

Bits [2:0] mapped to Secure Boot Authentication Scheme,
where:
000b: SHA2-512 Hash (not recommended)
001b: 3072-bit RSA
010b: ECDSA P-256 Curve
011b: ECDSA P-521-Curve
100b: Ed25519

please see-also Topic 370493.
any key mismatch lead to failed to burn fuses errors.

Hi @JerryChang

Yes, I am aware. However, I do not have those bits burned on either AGXs I’ve tried. Here’s the readout from the other AGX:

PublicKeyHash: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
BootSecurityInfo: 00000000
ArmJtagDisable: 00000000
SecurityMode: 00000000
SwReserved: 00000008
DebugAuthentication: 00000000
OdmId: 0000000000000000
BootDevInfo: 00000100
OdmLock: 00000000
ReservedOdm0: 00000000
ReservedOdm1: 00000000
ReservedOdm2: 00000000
ReservedOdm3: 00000000
ReservedOdm4: 00000000
ReservedOdm5: 00000000
ReservedOdm6: 00000000
ReservedOdm7: 00000000

trying to burn the SwReserved bits with modified xml to match the current fuse states except for the bit I want to set shows the same result:

<genericfuse MagicId="0x45535546" version="1.0.0">
        <fuse name="BootDevInfo" size="4" value="0x00000100"/>
        <fuse name="SwReserved" size="4" value="0x00000088"/>
</genericfuse>
I> Burning fuses
I> 1. Start BootDevInfo burn
I> Fuse is already burned with the same value
I> 1. BootDevInfo burn skipped
I>
I> 2. Start SwReserved burn
E> FUSE: Failed to burn fuse addr: 0xc5.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Failed burn fuses as per fuse info.
E> FSKP: Failed to burn fuses.
C> Task 0x0 failed (err: 0x62170302)
E> Top caller module: FSKP, error module: FUSE, reason: 0x02, aux_info: 0x03
I> Busy Spin

My question is why is it failing to write fuse?

E> FUSE: Failed to burn fuse addr: 0xc5.
E> FUSE: Could not write Fuse: 0x2c.
E> FUSE: Could not write Fuse: 0x2c.

hello joseph.gao,

it’s FUSE_RESERVED_SW_0 of Bit [1:0] for Boot device select.
as you can see in [Table 3. Boot Selection Register], it should be 0x1=QSPI by default.

besides.. may I have more details of programming SwReserved to 0x88.

Hi JerryChang

Joseph tried to set SwReserved to 0x88 because he tried to burn the fuses with odmfuse.sh, which resulted on SwReserved to be 0x08 instead of the expected 0x80. It was an attempt to achieve USB3 configuration despite the failed attempt with odmfuse.sh.

Can you help with the following questions:

Why did requesting SwReserved=0x80 apparently result in 0x08?

Can the affected modules still support USB3 recovery with reachable values such as SwReserved=0x88?

Is odmfuse.sh supported for this operation (Enablement of USB3 recovery mode) on Jetson Linux 36.4, or is fskp_fuseburn.py mandatory?

Thank you.

hello jacob.valadez,

it should not requesting SwReserved=0x80 to result in 0x08.
the bit may have been programmed by another operation.

yes, you can use odmfuse.sh to set bit-7 of FUSE_RESERVED_SW to enable USB SS mode for RCM.

@JerryChang

I am commanding SwReserved=0x80 and the result is 0x08. This was repeated on two different AGXs. The incorrectly programmed bit was not programmed by another operation. Are you try and reproduce this on your end by following the same steps I have listed above?

hello joseph.gao,

please refer to developer guide, Enabling AGX Orin, Orin NX, and Orin Nano in USB3 Recovery Mode.
for instance,

<genericfuse MagicId="0x45535546" version="1.0.0">
<fuse name="BootDevInfo" size="4" value="0x00000900"/>
<fuse name="SwReserved" size="4" value="0x00000080"/>
</genericfuse>

FYI,
the supported recovery connector’s SS signals are mapped to USB3 port 1, UPHY lane 1, PLL1
– BootDevInfo[10:8] = 001: USB3 port 1 / UPHY lane 1
– BootDevInfo[11] = 1: use the right-side PLL, PLL1
therefore.. BootDevInfo = 0x100 + 0x800 = 0x900. (for NVIDIA developer kits)
also, it’s bit-7 of SwReserved = 0x80 which actually enables SuperSpeed RCM.

after fuse burn, please connect the recovery port directly to a known USB3-capable host port with a USB3 cable, please check with $ lsusb -t, it should reported with 5-Gbps SuperSpeed (i.e. 5000M)