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.py implementation. 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.

  1. Download fskp_fuseburn_py-<version>.tgz from 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/
    
  2. Install python3-usb.

    sudo apt-cache search pyusb
    sudo apt install python3-usb
    
  3. 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)#

  1. Relaunch the container if it has exited.

  2. Untar the fskp_fuseburn_py tarball 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
    
  3. 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
    
  4. 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.

  5. Update tegrasign_v3_debug.yaml and 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 minimum FSKP_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.py interface, see the Secure Platform Dev Guide -> HSM Integration for Flashing.

  6. 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.xml in production. Use your OEM-approved production fuse XML file, such as fskp_fuse_t264.xml or fuse_t264.xml, created during the FSKP onboarding process. The --hsm fskp_kdk option sources the FSKP KDK key from your HSM via tegrasign_v3_hsm.py. The production key context should be used in place of the debug key context (0xffffffffffffffffffffffffffffffff). Do not add -v or --verbose for production FSKP runs.

  7. 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)#

  1. Relaunch the container if it has exited.

  2. Untar the fskp_fuseburn_py tarball 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
    
  3. 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
    
  4. 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
    
  5. 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
    
  6. Modify tegrasign_v3_debug.yaml for Chain B signing keys. Update the SIGN_KEY_LIST to 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.yaml and porting tegrasign_v3_hsm.py to interface with your HSM.

  7. 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 as 0rsa or 10eddsa. The key slot must be defined in tegrasign_v3_debug.yaml under SIGN_KEY_LIST.

  8. 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_PATH and set it to tegrasign_v3.py instead of using PRIVATE_KEY_PATH. This routes DU package signing through your HSM via tegrasign_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
    
  9. 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)#

  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
    
  2. 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
    
  3. 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)#

  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>
    
  2. Copy fskp_bct_copy_and_aurix_reset.sh to the host.

    cp fskp_bct_copy_and_aurix_reset.sh $DRIVE_FLASHING/fskp_bct_copy_and_aurix_reset.sh
    
  3. Copy the script to the target.

    scp $DRIVE_FLASHING/fskp_bct_copy_and_aurix_reset.sh $TARGET_HOST:/tmp/
    
  4. Run the script on the target.

    sudo /tmp/fskp_bct_copy_and_aurix_reset.sh
    

    Expected 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.

  1. 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
    
  2. 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
    
  3. 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/
    
  4. 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