Asymmetric Boot Chain for Linux#
This topic describes how to build, merge, flash, and update the Asymmetric Boot Chain (ABC) for Linux.
Note
This functionality should only be used by NVONLINE users who have the necessary agreements in place. For more details, contact your NVIDIA representative.
Note
These steps are for the production asymmetric boot flow in Prod/Prod mode. Replace placeholders such as BOARD_NAME, BUILD_DIR, <version>, and <docker-artifactory-path> with platform-specific values before running any commands. Placeholders appear in the Variables section and in the inline command examples.
Responsibilities#
This flow is split across two parties. Each part of this document is labeled with the responsible party in its section header.
Part |
Description |
Responsibility |
|---|---|---|
Part 1 |
Host setup |
Shared prerequisite for each party in its own environment |
Part 2 |
ABC build in the Chain A container |
Tier-1 |
Part 3 (steps 1–9) |
Chain B image build, DU package-2 creation, and DU utility compilation |
OEM |
Part 3 (steps 10–12) |
Chain A and Chain B merge and target flashing |
Tier-1 |
Part 4 |
Fusing |
Tier-1 |
Part 5 |
Merged image reflash and DU package-2 cloning on target |
OEM |
Prerequisites#
Access to NvOnline and the Drive Secure Platform SDK package.
Docker images for Chain A and Chain B, as well as the MODS docker container for fusing steps.
Network access to artifactory paths.
Target system reachable over SSH.
OEM-provisioned signing keys, including SBK, KEK, FSKP, PKC, and ED25519 keys.
OEM HSM and a ported
tegrasign_v3_hsm.pyimplementation. For HSM integration details, see the Secure Platform Dev Guide -> HSM Integration for Flashing.OEM production fuse XML file from the FSKP onboarding process.
Variables#
Set these variables before running commands. Adjust paths to your environment.
export BOARD_NAME=<board-name>
export BUILD_DIR=<build-dir>
export PDK_TOP=<pdk-top>
export LINUX_DIR=<linux-dir>
export DRIVE_FLASHING=/drive_flashing
export BOOT_CHAIN_DEV=/boot-chain-dev
export TARGET_IP=<target-ip>
export TARGET_HOST=nvidia@$TARGET_IP
Part 1 - Host Setup (Precondition)#
Before building ABC, copy the required tarballs to the host. These packages are part of the Drive Secure Platform SDK on NvOnline.
Download
fskp_fuseburn_py-<version>.tgzfrom artifactory and copy it to the host.Example source path:
edge.urm.nvidia.com/artifactory/sw-driveos-additional-sdk-generic-local/linux/drive-secure-platform-sdk/<release-version>/fskp_fuseburn_py-<version>.tgz
Example copy command:
cp <source>/fskp_fuseburn_py-<version>.tgz $DRIVE_FLASHING/
Install
python3-usb.sudo apt-cache search pyusb sudo apt install python3-usb
Create the Chain A docker container. Repeat this step for Chain B with the same flags.
sudo docker run -it --privileged --name chain_a --net host \ -v $BOOT_CHAIN_DEV:$BOOT_CHAIN_DEV -v /dev:/dev -v $DRIVE_FLASHING:$DRIVE_FLASHING \ <docker-artifactory-path>
Example with literal paths:
sudo docker run -it --privileged --name chain_a --net host -v /boot-chain-dev:/boot-chain-dev -v /dev:/dev -v /drive_flashing/:/drive_flashing/ <docker-artifactory-path>
Part 2 - Build ABC in the Chain A Container (Tier-1)#
Relaunch the container if it has exited.
Untar the
fskp_fuseburn_pytarball and set environment variables.export PDK_TOP=${PWD} export BOARD_NAME=<board-name> export BUILD_DIR=<build-dir> cp $DRIVE_FLASHING/fskp_fuseburn_py-<version>.tgz . tar xzvpf fskp_fuseburn_py-<version>.tgz
Verify that the required files are present in the container.
ls -l /drive/drive-foundation/tools/flashtools/fuseburn/fskp_fuseburn.py ls -l /drive/drive-foundation/firmware/bin/t264/fskpboot/fskp.bin
Stage your OEM signing keys in the container. Copy your key files, including SBK, KEK, FSKP, PKC, and ED25519 keys, to the flash tools key directory.
cp -prv <path-to-your-oem-keys> \ /drive/drive-foundation/tools/flashtools/flash/oem_keys
Note
In production, you must use your own OEM-provisioned keys. Do not use the NVIDIA-provided test keys.
Update
tegrasign_v3_debug.yamland integrate your HSM. Ensure the file maps all key roles to your OEM HSM key identifiers, and update any key filenames or paths that differ in your environment, at minimumFSKP_KDK_KEY.For production, integrate your HSM by following the instructions in the Secure Platform Dev Guide -> HSM Integration for Flashing.
Note
For details on HSM integration and the
tegrasign_v3_hsm.pyinterface, see the Secure Platform Dev Guide -> HSM Integration for Flashing.Generate the FSKP fuse blob using your OEM production fuse XML and HSM.
${PDK_TOP}/drive-foundation/tools/flashtools/fuseburn/fskp_fuseburn.py \ -c 0x26 -f <path-to-your-production-fuse-xml> \ -g ${PDK_TOP}/drive-foundation/firmware/bin/t264/fskpboot \ -i <key-context> -B $BOARD_NAME -b \ --hsm fskp_kdk \ --key-exp t264_fskp_ak.key t264_fskp_ek.key
Note
Do not use
sample_fskp_fuse_t264.xmlin production. Use your OEM-approved production fuse XML file, such asfskp_fuse_t264.xmlorfuse_t264.xml, created during the FSKP onboarding process. The--hsm fskp_kdkoption sources the FSKP KDK key from your HSM viategrasign_v3_hsm.py. The production key context should be used in place of the debug key context (0xffffffffffffffffffffffffffffffff). Do not add-vor--verbosefor production FSKP runs.Build Chain A images.
${PDK_TOP}/drive-foundation/make/bind_partitions -b ${BOARD_NAME} drive_av.linux -z -p mods clean ${PDK_TOP}/drive-foundation/make/bind_partitions -b ${BOARD_NAME} drive_av.linux -z -p mods ${PDK_TOP}/drive-foundation/tools/flashtools/bootburn/create_bsp_images.py \ -b ${BOARD_NAME} -r 1 -g ${PDK_TOP}/${BUILD_DIR}/chain_a \ -D --chain A --asymmetric \ --fskp-bct-path ${PDK_TOP}/drive-foundation/firmware/bin/t264/fskpboot/br_bct_BR_sigheader.bct -m
Chain A image generation is complete.
Part 3 - Build ABC in the Chain B Container#
Part 3 is split by responsibility. In steps 1 through 9, the OEM produces Chain B images, the Drive Update package-2, and the DU utilities. The OEM then hands off the Chain B images to Tier-1 for steps 10 through 12, which cover chain merging and target flashing. The OEM retains package-2 and the compiled DU utilities for use on the target in Part 5.
Part 3.1 - Build Chain B Images and DU Package-2 (OEM)#
Relaunch the container if it has exited.
Untar the
fskp_fuseburn_pytarball and set environment variables.export PDK_TOP=${PWD} export BOARD_NAME=<board-name> export BUILD_DIR=<build-dir> cp $DRIVE_FLASHING/fskp_fuseburn_py-<version>.tgz . tar xzvpf fskp_fuseburn_py-<version>.tgz
Verify that the required files are present in the container.
ls -l /drive/drive-foundation/tools/flashtools/fuseburn/fskp_fuseburn.py ls -l /drive/drive-foundation/firmware/bin/t264/fskpboot/fskp.bin
Stage your OEM signing keys inside the Chain B container, as done for Chain A.
cp -prv <path-to-your-oem-keys> \ /drive/drive-foundation/tools/flashtools/flash/oem_keys
Build Chain B base partitions.
${PDK_TOP}/drive-foundation/make/bind_partitions -b ${BOARD_NAME} drive_av.linux -p dev_nsr \ ENABLE_SKIP_ECID_CHECK=y ENABLE_GOS0_NVLOG=n OS_ARGS_ROOT_MOUNT_PER=ro clean ${PDK_TOP}/drive-foundation/make/bind_partitions -b ${BOARD_NAME} drive_av.linux -p dev_nsr \ ENABLE_SKIP_ECID_CHECK=y ENABLE_GOS0_NVLOG=n OS_ARGS_ROOT_MOUNT_PER=ro
Modify
tegrasign_v3_debug.yamlfor Chain B signing keys. Update theSIGN_KEY_LISTto reference your OEM key files for each slot.For production HSM integration, see the Secure Platform Dev Guide -> HSM Integration for Flashing for details on configuring
tegrasign_v3_debug.yamland portingtegrasign_v3_hsm.pyto interface with your HSM.Create Chain B images.
${PDK_TOP}/drive-foundation/tools/flashtools/bootburn/create_bsp_images.py \ -b ${BOARD_NAME} --no_du_pvit -r 1 -g ${PDK_TOP}/${BUILD_DIR}/chain_b \ -D --chain B --asymmetric --hsm <index><algo>
The
--hsm <index><algo>argument selects the OEM key slot 0–15 and the signing algorithm, such as0rsaor10eddsa. The key slot must be defined integrasign_v3_debug.yamlunderSIGN_KEY_LIST.Create Drive Update (DU) package-2 in the Chain B container.
export PDK_TOP=${PWD} export BOARD_NAME=<board-name> export BUILD_DIR=<build-dir> cd /drive/drive-foundation/tools/driveupdate/dupkg # Skip these two steps if recreating package-2 python3 setup.py build python3 setup.py install TEGRA_A_SRC=${PDK_TOP}/${BUILD_DIR}/chain_b/642-63960-0010-000_TS3/flash-images time python3 dupkg/dupkg.py gen --in TII_META_VER=metav2 TEGRA_A_SRC="$TEGRA_A_SRC" \ VALIDATE_OPTION=True SHA_ALG=sha512 AUTHENTICATOR_OPTION=AuthPkg \ TEGRASIGN_PATH=${PDK_TOP}/drive-foundation/tools/flashtools/flash/tegrasign_v3.py \ CHAIN=B ERASE_PADDING_FLAG=0 \ --template dupkg_clone_template --out /drive_flashing/package-2 \ 2>&1 | tee package-2_use_dupkg_clone_template.log
Note
For production HSM signing, use
TEGRASIGN_PATHand set it totegrasign_v3.pyinstead of usingPRIVATE_KEY_PATH. This routes DU package signing through your HSM viategrasign_v3_hsm.py.Expected output:
DRIVE Update Packaging Tool Version 1.6.1 Generating packages... Done real 0m0.622s user 0m0.432s sys 0m0.035s
Compile DU utilities in the Chain B container.
cd /drive/drive-linux/samples/driveupdate/content_server make cd /drive/drive-linux/samples/driveupdate/sample_client_app make
At this point, the OEM hands off the generated Chain B images to Tier-1 for merging and flashing. The OEM retains package-2 and the compiled DU utilities for use on the target in Part 5.
Part 3.2 - Merge and Flash (Tier-1)#
Copy Chain A images to a shared volume for merge.
cp -pr ${PDK_TOP}/${BUILD_DIR}/chain_a $BOOT_CHAIN_DEV/ ls -l ${PDK_TOP}/${BUILD_DIR}/chain_a ls -l $BOOT_CHAIN_DEV/chain_a
Create merged images in Chain B.
${PDK_TOP}/drive-foundation/tools/flashtools/bootburn/create_bsp_images.py \ -b ${BOARD_NAME} -r 1 -g ${PDK_TOP}/${BUILD_DIR}/merge_output_directory \ -D --asymmetric \ --merge-chains A=$BOOT_CHAIN_DEV/chain_a B=${PDK_TOP}/${BUILD_DIR}/chain_b
Flash merged images.
${PDK_TOP}/drive-foundation/tools/flashtools/bootburn/flash_bsp_images.py \ -b ${BOARD_NAME} -P ${PDK_TOP}/${BUILD_DIR}/merge_output_directory/642-63960-0010-000_TS3 \ -D --asymmetric
Chain merge and flash are complete.
Part 4 - Fusing (Tier-1)#
Launch MODS docker container.
sudo docker run --rm -it --privileged --net host \ -v $BOOT_CHAIN_DEV:$BOOT_CHAIN_DEV -v /dev:/dev -v $DRIVE_FLASHING:$DRIVE_FLASHING \ <mods-docker-artifactory-link>
Copy
fskp_bct_copy_and_aurix_reset.shto the host.cp fskp_bct_copy_and_aurix_reset.sh $DRIVE_FLASHING/fskp_bct_copy_and_aurix_reset.sh
Copy the script to the target.
scp $DRIVE_FLASHING/fskp_bct_copy_and_aurix_reset.sh $TARGET_HOST:/tmp/
Run the script on the target.
sudo /tmp/fskp_bct_copy_and_aurix_reset.shExpected output:
========================================== FSKP BCT Copy Script ========================================== [INFO] Searching for QSPI device with A_bct partition... [INFO] Found storage device: tegra_virt_storage70, partition: A_bct [INFO] Found A_bct partition on tegra_virt_storage70 [INFO] Found QSPI device for A_bct: /dev/mtdblock1 [INFO] Device path: ../devices/platform/tegra_virt_storage70/mtd/mtd1/mtdblock1 [INFO] QSPI device /dev/mtdblock1 found [INFO] Device permissions verified [INFO] Device size: 256KB [INFO] Starting automated FSKP BCT copy operation [INFO] Device: /dev/mtdblock1 [INFO] Operation: Copy 16KB from 128KB to 0KB [INFO] Creating backup of QSPI device to /tmp/qspi_backup_20250807_232835.bin [INFO] Backup created successfully: /tmp/qspi_backup_20250807_232835.bin [INFO] Starting FSKP BCT copy operation... [INFO] Source: 128KB offset [INFO] Destination: 0KB offset [INFO] Size: 16KB [INFO] Copying source data to temporary file... [INFO] Writing data to destination... [INFO] BCT copy operation completed successfully [INFO] Copy operation completed [INFO] Verifying copy operation... [INFO] Copy verification successful - data matches [INFO] FSKP BCT copy operation completed successfully! [INFO] Sending aurix reset command to SMCU... [INFO] Aurix reset command sent successfully [INFO] Cleaned up temporary file: /tmp/qspi_bct_16kb.bin
Part 5 - Reflash and Clone Drive Update (DU) Package-2 on Target (OEM)#
This part runs after Tier-1 completes chain merging and flashing in Part 3.2 and completes fusing in Part 4. The OEM uses the package-2 and DU utilities produced in Part 3.1, steps 8 and 9.
Reflash merged image.
${PDK_TOP}/drive-foundation/tools/flashtools/bootburn/flash_bsp_images.py \ -b ${BOARD_NAME} -P ${PDK_TOP}/${BUILD_DIR}/merge_output_directory/642-63960-0010-000_TS3 \ -D --asymmetric
In the MCU console, run the following to select Chain B using GPIO.
setbtchnsel gpio setdfltbtchain x1 B aurixreset
Expected output:
INFO: MCU_PLTFPWRMGR: Bootchain selection mode: GPIO INFO: BtChn_Cfg: Tegra x1 Boot Chain is : B
Copy package-2 and DU utilities to the target.
scp /drive/drive-linux/samples/driveupdate/sample_client_app/sample_driveupdate $TARGET_HOST:/tmp/ scp /drive/drive-linux/samples/driveupdate/content_server/content_server $TARGET_HOST:/tmp/ scp -pr /drive_flashing/package-2 $TARGET_HOST:/tmp/
Start DU on the target.
cd /tmp sudo ./content_server package-2 & sudo ./sample_driveupdate -p /content/files --auth
Expected output:
nvidia@tegra-ubuntu:/mnt/persistent/metadata$ nvidia@tegra-ubuntu:/mnt/persistent/metadata$ sudo ./content_server package-2 & [1] 2913 nvidia@tegra-ubuntu:/mnt/persistent/metadata$ [INFO]Serve DUPKG at 'package-2' Files are successfully exported to dulink nvidia@tegra-ubuntu:/mnt/persistent/metadata$ nvidia@tegra-ubuntu:/mnt/persistent/metadata$ nvidia@tegra-ubuntu:/mnt/persistent/metadata$ sudo ./sample_driveupdate -p /content/files --auth [INFO]Failed to read persistent context, assuming empty [INFO]Auth DU Package: auth_conf.json is found Deploy mode is pull Current state: STATE_DORMANT Update is waiting for higher run level 4 Current state: STATE_UPDATE_IN_PROGRESS, progress 0% Current state: STATE_UPDATE_IN_PROGRESS, progress 0% Current state: STATE_UPDATE_IN_PROGRESS, progress 0% Current state: STATE_UPDATE_IN_PROGRESS, progress 0% Current state: STATE_UPDATE_IN_PROGRESS, progress 0% Current state: STATE_UPDATE_IN_PROGRESS, progress 0% .... Current state: STATE_UPDATE_IN_PROGRESS, progress 33% Current state: STATE_UPDATE_IN_PROGRESS, progress 33% Current state: STATE_UPDATE_IN_PROGRESS, progress 33% Current state: STATE_UPDATE_IN_PROGRESS, progress 33% pl:[I]: UTC init successful pl:[I]: storage is virtualized pl:[I]: device_registration_virt_init Successful pl:[I]: RSA_PSS authentication for binary PASSED pl:[I]: EDDSA authentication for binary successful pl:[I]: XMSS authentication for binary successful pl:[I]: xmss_verify_test done pl:[I]: KAT successful pl:[I]: PVIT Loaded pl:[I]: Platform ChipId 0x26 pl:[I]: BCH SHA512 digest verification successful pl:[I]: signtype read as eddsa pl:[I]: PCP SHA512 hash validation successful pl:[I]: EDDSA authentication for binary successful pl:[I]: PVIT entry found and SHA is matching pl:[I]: Loaded PT pl:[I]: Booted chain A ....
Expect the target to auto-reboot into Chain A after the package-2 clone completes.
MCU output:
INFO: MCU_PLTFPWRMGR: Bootchain selection mode: GPIO <== PASS INFO: BtChn_Cfg: Using Next Bootchain for SOC bootup.. INFO: BtChn_Cfg: Tegra x1 Boot Chain is : A