.. _SD.Bootloader.UpdateAndRedundancy:

.. include:: /content/swdocs.rsts

.. spelling::
   agx
   autosync
   BUP
   ies
   nv
   tx
   xCAFE
   jetson
   xavier
   nx
   devkit
   EF
   emmc
   ota


Update and Redundancy
!!!!!!!!!!!!!!!!!!!!!

|NVIDIA(r)| |Jetson(tm)| Linux supports Bootloader update and redundancy on all Jetson platforms.

The Bootloader update process performs a safe Bootloader update and ensures
that a workable Bootloader partition remains available during an
update. It accomplishes this using **A/B update**, a feature that maintains
two sets of Bootloader partitions, **Slot A** and **Slot B**, each of which is a
complete set of the partitions that contain boot images.

Bootloader redundancy is enabled by default.

A/B Slot Layout
@@@@@@@@@@@@@@@

The principle of shadow copying enables multiple placeholders. All of the
placeholders but one hold backup copies. Each backup copy is a
candidate to boot from. However, based on runtime decisions,
the correct copy of the binary is loaded to continue with the boot
process. These two shadow copies are commonly referred to as Slot A and
Slot B. This two-slot implementation is as follows:


.. figure:: UpdateAndRedundancy/SlotImplementationLayout.svg
   :figwidth: 300px

The diagram above shows the slot implementation in conceptual form.

A/B System Update
@@@@@@@@@@@@@@@@@

An A/B slot update affects these components:

- `Partition Selection <#partition-selection>`__
- `Update Engine <#update-engine>`__

Partition Selection
###################

A/B system updates use two sets of partitions (slots). Each slot has several attributes:

-  The slot that the running system booted from is called the **current slot**.
   The other slot is called the **unused slot**. The system exchanges the roles of the current and unused slot in the course of an
   update, or when the software fails repeatedly during or immediately after a boot.

-  The slot that the system will use the next time it boots is called the **active slot**. In "steady state" device the bootable slot is also the active slot. When the system is being updated it may be different.

-  A slot's **status attribute** indicates whether the slot contains a
   system from which the device should be able to boot. When the system
   is running the current slot is bootable; the unused slot may have an
   older, identical, or newer version of the system, and may or may not
   be bootable.

The bootable slot is the slot whose **status attribute** is ``normal``.

If a bootable slot fails to boot, Bootloader sets its status attribute as ``unbootable`` and switches the roles of the current and unused slots.
The formerly unused, now current, slot typically contains boot software that is one update old (if the device was just updated with nonfunctional software)
or current (if the former current slot has suffered data corruption).

Update Engine
#############

The A/B system update uses the Update Engine to update the A and B slots and
prepares the system to boot an updated version of Bootloader. The Update
Engine performs these actions:

1. Reads ``bl_update_payload`` and writes GPT partition.

2. Reads ``bl_update_payload`` and writes data to the non-current slot
   partitions as instructed by the payload.

3. Writes data to the current slot partitions as instructed by the payload.

For more information, refer to `Running the Update Engine <#running-the-update-engine>`__.

.. note::
  - The current Update Engine only supports updates to slots A and B at the same time.

  - During the update, do not power down or reset the Jetson device.

  - The Update Engine is only used to update Bootloader before release 35.2.

Bootloader Implementation
@@@@@@@@@@@@@@@@@@@@@@@@@

The A/B system uses the Scratch Register to store the slot status. It
is used between the cpu-bootloader and early stage Bootloader. The early
stage Bootloader runs the state machine to select the boot slot. It handles
the update failure cases as follows:

.. figure:: UpdateAndRedundancy/UpdateFailure.svg
   :figwidth: 650 px

Here is the process flow:

  - For |NVIDIA(r)| |Jetson AGX Orin(tm)|: BootRom uses the BR-BCT to find the current slot for cold boot,
    and it uses the Scratch Register to find the current slot for warm boot. It marks the current slot status
    as ``invalid`` and caches the current slot number, 0 (slot A) or 1 (slot B), with the status flag in scratch
    register 109. This slot number will be used by MB1, MB2, UEFI, or later stage loaders. When control reaches
    cpu-bootloader, it restores the status flag to ``valid`` and saves to the scratch register 109.

  - For |NVIDIA(r)| |Jetson AGX Xavier(tm)| and |NVIDIA(r)| |Jetson Xavier(tm) NX|: BootRom uses the BR-BCT to
    find the current slot for cold boot, and it uses the Scratch Register to find the current slot for warm boot.
    It caches the current slot number, 0 (slot A) or 1 (slot B) in scratch register 99, and MB1 reads the current
    slot number from the scratch register 99. It marks the current slot status as ``invalid`` and caches the current
    slot number with the status flag in scratch register 15. The cached slot number will be used by MB2, UEFI, or
    later stage loaders. When control reaches cpu-bootloader, it restores the status flag to ``valid`` and saves
    the updated state to scratch register 15.

If BootRom does not find a current slot, the device enters NVIDIA recovery mode.

.. note:: The Cpu-bootloader automatically updates the slot number in BR-BCT when the following conditions are met:

  - The slot number in BR-BCT does not match the current slot number in the scratch register.

  - The UEFI variable ``AutoUpdateBrBct`` is set to 1, and this value is configured by ``L4TConfiguration.dts`` in UEFI source.


Bootloader Scratch Register
###########################

This section provides information about the Scratch register definition.

For |NVIDIA(r)| |Jetson AGX Orin(tm)|
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

+------------------------------------+
| Scratch register 109 layout        |
+----------+-------------------------+
| Bits     | Contents                |
+==========+==========+==============+
| 31-6     | Reserved                |
+----------+-------------------------+
| 5-4      | Current slot number     |
+----------+-------------------------+
| 3-0      | Boot slot status flag   |
+----------+-------------------------+

  Where:

  - The current slot number is ``0`` for slot A and ``1`` for slot B.

  - The boot slot status flag uses bits to indicate the following slot statuses:

    - ``0``: valid

    - ``1``: invalid

    For example, 0001b means slot A is invalid.

For |NVIDIA(r)| |Jetson AGX Xavier(tm)| and  |NVIDIA(r)| |Jetson Xavier(tm) NX|
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

+------------------------------------+
| Scratch register 15 layout         |
+----------+-------------------------+
| Bits     | Contents                |
+==========+==========+==============+
| 31-27    | Reserved                |
+----------+-------------------------+
| 26       | Update BR-BCT flag      |
+----------+-------------------------+
| 25-22    | Boot slot status flag   |
+----------+-------------------------+
| 21-19    | Maximum number of slots |
+----------+-------------------------+
| 18-16    | Current slot number     |
+----------+-------------------------+
| 15-0     | Magic pattern 0x4EF1    |
+----------+-------------------------+

  Where:

  - The current slot number is ``0`` for slot A and ``1`` for slot B.

  - Maximum number of slots: the maximum number of bootloader slots. For the current system it is two, slot A and slot B.

  - The boot slot status flag uses bits to indicate the following slot statuses:

    - ``0``: valid

    - ``1``: invalid

    For example, 0001b means slot A is invalid.

  - The boot slot status flag uses bits to notify the cpu-bootloader to update the BR-BCT:

    - ``0``: not update

    - ``1``: update

Partition Settings
##################

For |NVIDIA(r)| |Jetson AGX Orin(tm)|
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

The A/B partitions must use the following naming convention:

-  ``A_mb1``
-  ``B_mb1``
-  ``A_mb2``
-  ``B_mb2``
-  ``A_cpu-bootloader``
-  ``B_cpu-bootloader``
-  etc

The name of the partition that is being loaded is derived as follows::

   partition_name = "<slot_value>"_<base_name>
   slot value = "A" for slot 0
   slot value = "B" for slot 1

For |NVIDIA(r)| |Jetson AGX Xavier(tm)| and  |NVIDIA(r)| |Jetson Xavier(tm) NX|
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

The A/B partitions must use the following naming convention:

-  ``mb1``
-  ``mb1_b``
-  ``mb2``
-  ``mb2_b``
-  ``cpu-bootloader``
-  ``cpu-bootloader_b``
-  etc

The name of the partition that is being loaded is derived as follows::

   partition_name = <base_name>"<slot_value>"
   slot value = "" for slot 0
   slot value = "_b" for slot 1

The empty suffix for Slot A ensures backward compatibility with legacy partition loading mechanisms that are unaware of A/B slots.

Update Bootloader
@@@@@@@@@@@@@@@@@

The bootloader update is triggered by the Update Engine and verified by the Boot Control:

- The user enters the following command, which launches the Update Engine to update the software in both slot A and B::

     $ sudo nv_update_engine --forced-install

  The Update Engine updates the software by applying a Bootloader update payload (BUP). The BUP must be named ``bl_update_payload`` and
  must be placed in the ``/opt/ota_package`` directory.

- The boot service enters the following command to launch the Boot Control during a system boot::

     $ sudo nvbootctrl verify

  The Boot Control runs a predefined workflow.

Bootloader Tools
@@@@@@@@@@@@@@@@

NVIDIA provides tools for ease of use in the Bootloader update process.

Boot Control
############

``nvbootctrl`` is intended to be used for debugging, so it can be used to dump the slot information. You can also use it to set the active slot,
which forces the boot slot to change for the next boot.

To display the command usage, run the following command with no parameters::

   $ sudo nvbootctrl

For more information, refer to `Manually Modifying Boot Slots <#manually-modifying-boot-slots>`__.

Bootloader Update Payload Generator
###################################

The Bootloader Update Payload (BUP) is the payload that is applied by
the update engine during an update. The BUP is generated by the host
tool ``build_l4t_bup.sh``, kept with ``flash.sh``
in the Linux for Jetson Board Support Package (BSP).

This section describes procedures for generating a multi-spec BUP or a single-spec BUP.

A **multi-spec** BUP includes firmware binaries and BCT images for each supported Jetson device. When you run the updater, it uses the appropriate binary of each type for the device you are updating.

A **single-spec** BUP includes firmware binaries and BCT images for just one type of device. It is appropriate if you are updating just one type of Jetson device.

- To generate a multi-spec BUP or a single-spec BUP, refer to `Generating the Bootloader Update Payload (BUP) <#generating-the-bootloader-update-payload-bup>`__.

The multi-spec procedure stores a BUP at each of these locations for the
respective group of processors. The single-spec procedure stores a BUP
at just one location for the appropriate type of processor.

You must place the appropriate BUP file on the target system under this directory before the Update Engine is run::

   /opt/ota_package/


Running the Update Engine
@@@@@@@@@@@@@@@@@@@@@@@@@

Run the Update Engine on the Jetson device.

To Update Bootloader
####################

1. Run the following command on the Jetson device to switch to superuser mode::

      $ sudo su

2. If no BUP directory exists, create one by running the command::

      # mkdir /opt/ota_package

3. To copy the BUP from the host system to the BUP directory, run the following command::

      # scp <host_loc:bl_update_payload> /opt/ota_package/

   Where:

   - ``<host_loc:bl_update_payload>`` is the location where the BUP is built on the host system. You can also use a USB drive to copy the BUP from the host system to the target system.

   -  For information about how to generate the BUP, refer to `Generating the Bootloader Update Payload (BUP) <#generating-the-bootloader-update-payload-bup>`__.

4. To launch the Update Engine to update Bootloader on both slots(slot A and slot B), run the following command::

      # nv_update_engine --forced-install

.. note::
  - The update will take about 5 minutes.

Manually Modifying Boot Slots
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

NVIDIA provides the ``nvbootctrl`` tool for testing and development purposes. However, you may wish to switch boot slots manually from user space.

To manually modify the boot slots
#################################

1. Run the following command to switch to superuser mode::

      $ sudo su

2. Run the following command::

      # nvbootctrl <command>

   Where ``<command>`` is one of the values in the following table:

.. list-table::
   :widths: auto
   :header-rows: 1

   * - Command
     - Description

   * - get-number-slots
     - Prints the number of slots.

   * - get-current-slot
     - Prints the currently running slot.

   * - dump-slots-info
     - Prints information about the slots.

   * - set-active-boot-slot <slot>
     - At the next boot, loads and executes ``<slot>``.

   * - verify
     - Verifies the bootloader and the rootfs boot.

   * - set-SR-BR <slot>
     - On next warm reset, loads and executes ``<slot>``. (only the T194 bootloader).

   * - is-rootfs-ab-enabled
     - Rootfs only, return:
        - 0: Rootfs A/B is disabled.
        - 1: Rootfs A/B is enabled and current rootfs slot is A.
        - 2: Rootfs A/B is enabled and current rootfs slot is B.

.. note::
  - ``<slot>`` is the zero-based slot number.

  - The default setting for both slot 0 and slot 1 is "bootable".

To show the current boot slot
#############################

- Run the following command::

     # nvbootctrl get-current-slot

The command displays a single digit, 0 (slot A) or 1 (slot B).

To show the slot status
#######################

- Run the following command::

     # nvbootctrl dump-slots-info

  The command displays the status of both slots::

     Current version: 35.2.0
     Capsule update status: 0
     Current bootloader slot: A
     Active bootloader slot: A
     num_slots: 2
     slot: 0,             status: normal
     slot: 1,             status: normal

Sample Boot Log
@@@@@@@@@@@@@@@

The boot slot is selected by BootRom, and MB1 and MB2 use the slot number. The message displayed from MB1 is available from an MB1 debug build
that has messages enabled. Messages from MB2 are always available.

For |NVIDIA(r)| |Jetson AGX Orin(tm)|
#####################################

The following sample log shows that slot 1 (slot B) is selected as the boot slot::

   [0000.063] I> MB1 (version: 0.23.0.0-t234-54845784-92215740)
   [0000.068] I> t234-A01-0-Silicon (0x12347) Prod
   [0000.073] I> Boot-mode : Coldboot
   [0000.076] I> Emulation:
   [0000.078] I> Entry timestamp: 0x00000000
   [0000.082] I> last_boot_error: 0x0
   [0000.085] I> BR-BCT: preprod_dev_sign: 0
   [0000.089] I> rst_source: 0xb, rst_level: 0x1
   [0000.093] I> Task: CRC check (0x5001cf71)
   [0000.097] I> Skip CRC check as records_integrity fuse is not burned
    . . .
    . . .
   [0000.265] I> Loading MEM-BCT to SysRAM
   [0000.269] I> Scratch RSV109: 0x00000013    active chain: 1
   [0000.274] I> Slot: 1
   [0000.276] I> Binary[0] block-0 (partition size: 0x40000)
   [0000.281] I>  get_binary_info: Binary name: MEM-BCT-0
    . . .
    . . .
   I> MB2 (version: 0.0.0.0-t234-54845784-7aee5a6b)
   I> t234-A01-0-Silicon (0x12347)
   I> Boot-mode : Coldboot
   I> Emulation:
   I> Entry timestamp: 0x001f2b6f
   I> Regular heap: [base:0x40040000, size:0x10000]
    . . .
    . . .
   I> Successfully register APE FW load task with MB2 loader
   I> Skipping FSI FW load
   I> Successfully register XUSB FW load task with MB2 loader
   I> Scratch RSV109: 0x00000013    active chain: 1
   I> Partition name: B_spe-fw
   I> Size of partition: 589824
   I> Binary@ device:3/0 block-118016 (partition size: 0x90000), name: B_spe-fw
    . . .
    . . .

For |NVIDIA(r)| |Jetson AGX Xavier(tm)| and  |NVIDIA(r)| |Jetson Xavier(tm) NX|
###############################################################################

The following sample log shows that slot 1 (slot B) is selected as the boot slot::

   [0000.053] W> RATCHET: MB1 binary ratchet value 4 is larger than ratchet level 1 from HW fuses.
   [0000.061] I> MB1 (prd-version: 2.3.0.0-t194-41334769-0a17edc1)
   [0000.067] I> Boot-mode: Coldboot
   [0000.070] I> Platform: Silicon
   [0000.073] I> Chip revision : A02
   [0000.076] I> Bootrom patch version : 7 (correctly patched)
   [0000.081] I> ATE fuse revision : 0x200
   [0000.084] I> Ram repair fuse : 0x0
   [0000.087] I> Ram Code : 0x0
   [0000.090] I> rst_source: 0xb, rst_level: 0x1
   [0000.095] I> Boot-device: SDMMC (instance: 3)
   [0000.111] I> sdmmc DDR50 mode
   [0000.115] I> Boot chain mechanism: A/B
   [0000.118] I> Current Boot-Chain Slot: 1
   [0000.122] I> BR-BCT Boot-Chain: 0, status: 0. update flag: 1
   [0000.129] W> PROD_CONFIG: device prod data is empty in MB1 BCT.
   [0000.134] I> Temperature = 39500
   [0000.137] W> Skipping boost for clk: BPMP_CPU_NIC
   [0000.142] W> Skipping boost for clk: BPMP_APB
   [0000.146] W> Skipping boost for clk: AXI_CBB
   [0000.150] W> Skipping boost for clk: AON_CPU_NIC
   [0000.154] W> Skipping boost for clk: CAN1
   [0000.158] W> Skipping boost for clk: CAN2
   [0000.162] I> Boot-device: SDMMC (instance: 3)
   [0000.173] I> Sdmmc: HS400 mode enabled
   [0000.177] I> Non-ECC region[0]: Start:0x80000000, End:0x100000000
   [0000.184] W>  Thermal config not found in BCT
   [0000.192] W>  MEMIO rail config not found in BCT
   [0000.210] I> sdmmc bdev is already initialized
   [0000.255] W>  Platform config not found in BCT
   [0000.289] I> MB1 done

   main enter
   SPE VERSION #: R01.00.18 Created: Jan 29 2021 @ 14:18:27
   HW Function test
   Start Scheduler.
   in late init

   [0000.298] I> Welcome to MB2(TBoot-BPMP) (version: default.t194-mobile-23fd5458)
   [0000.299] I> DMA Heap @ [0x526fa000 - 0x52ffa000]
   [0000.299] I> Default Heap @ [0xd486400 - 0xd48a400]
   [0000.300] E> DEVICE_PROD: Invalid value data = 70020000, size = 0.
   [0000.306] W> device prod register failed
   [0000.310] I> gpio framework initialized
   [0000.313] I> tegrabl_gpio_driver_register: register 'nvidia,tegra194-gpio' driver
   [0000.321] I> tegrabl_gpio_driver_register: register 'nvidia,tegra194-gpio-aon' driver
   [0000.328] I> No valid sdcard_params in mb1_bct
   [0000.333] I> Boot_device: SDMMC_BOOT instance: 3
   [0000.337] I> sdmmc-3 params source = boot args
   [0000.346] I> sdmmc-3 params source = boot args
   [0000.347] I> sdmmc bdev is already initialized
   [0000.380] I> Found 20 partitions in SDMMC_BOOT (instance 3)
   [0000.395] I> Found 42 partitions in SDMMC_USER (instance 3)
   [0000.396] I> Active Boot chain : 1
   [0000.454] I> Relocating BR-BCT
   [0000.455]  > DEVICE_PROD: device prod is not initialized.
    . . .
    . . .

Generating the Bootloader Update Payload (BUP)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

A Bootloader Update Payload (BUP) is used to implement Bootloader
update. It contains firmware binaries of each type needed to update a
Jetson device.

This section describes the procedure for generating a single-spec BUP,
which contains just one binary of each type and can be used to update
just one Jetson device configuration.

There is also a procedure for generating a multi-spec BUP, which
includes multiple firmware binaries and BCT images of each type, and can
be used to update any supported type of Jetson device. When you run the
updater, it uses the appropriate binary of each type for the device you
are updating. Refer to `Generating a multi-spec BUP <#generating-a-multi-spec-bup>`__ for more information.

Generating a Single-Spec BUP
#############################

- To create a BUP image that will be stored in a file for a carrier board that is not connected to the host system:

  - For a Jetson AGX Orin carrier board with the indicated value of ``FAB``, ``BOARDID``, ``FUSELEVEL`` and ``BOARDSKU``::

       $ cd <top>
       $ sudo FAB=000 BOARDID=3701 FUSELEVEL=fuselevel_production BOARDSKU=0000 ./build_l4t_bup.sh jetson-agx-orin-devkit mmcblk0p1


  - For a Jetson Xavier NX carrier board with the indicated values of ``FAB``, ``BOARDID``, ``FUSELEVEL`` and ``BOARDSKU``::

       $ cd <top>
       $ sudo FAB=100 BOARDID=3668 FUSELEVEL=fuselevel_production BOARDSKU=0001 ./build_l4t_bup.sh jetson-xavier-nx-devkit-emmc mmcblk0p1


  - For a Jetson AGX Xavier carrier board with the indicated values of ``FAB``, ``BOARDID``, ``FUSELEVEL``, ``BOARDSKU`` and ``BOARDREV``::

       $ cd <top>
       $ sudo FAB=400 BOARDID=2888 FUSELEVEL=fuselevel_production BOARDSKU=0001 BOARDREV=H.0 ./build_l4t_bup.sh jetson-agx-xavier-devkit mmcblk0p1


- To create a BUP image for a board that is connected to the host system:

  1. Place the target board into :ref:`Force Recovery Mode <IN.QuickStart.ToFlashJetsonDeveloperKitOperatingSoftware-ForceRecoveryMode>`.

  2. Run the following commands::

      $ cd <top>
      $ sudo ./build_l4t_bup.sh <device> mmcblk0p1

   Where <device> is:

   - For Jetson AGX Orin: ``jetson-agx-orin-devkit``
   - For Jetson Xavier NX series: ``jetson-xavier-nx-devkit-emmc``
   - For Jetson AGX Xavier series: ``jetson-agx-xavier-devkit``

- To create the PKC signed BUP image for a carrier board connected to the host system:

  1. Place the target board into `Force Recovery Mode <IN.QuickStart-ToFlashJetsonDeveloperKitOperatingSoftware-ForceRecoveryMode>`__.

  2. Run the following commands::

       $ cd <top>
       $ sudo ./build_l4t_bup.sh -u <pkc_key_file> -v <sbk_key_file> <device> mmcblk0p1

     Where:

     - ``<top>`` is the location of the parent directory of the PDK installation package, in which ``flash.sh`` is stored.
     - ``<pkc_key_file>`` is the RSA private key file for your board. It must be in the ``<top>/bootloader`` directory, or you must specify its absolute pathname.
     - ``<sbk_key_file>`` is the Secure Boot Key (SBK) key file for your board. It must be in the ``<top>/bootloader`` directory, or you must specify its absolute pathname. This option must used with PKC key and currently support only Jetson Xavier NX series and Jetson AGX Xavier.
     - ``<device>`` is:

       - For Jetson AGX Orin series: ``jetson-agx-orin-devkit``
       - For Jetson Xavier NX series: ``jetson-xavier-nx-devkit-emmc``
       - For Jetson AGX Xavier series: ``jetson-agx-xavier-devkit``

Generating a Multi-Spec BUP
############################

- Run the following commands::

     $ cd <top>
     $ sudo ./l4t_generate_soc_bup.sh [-u <pkc_key_file>] [ -v <sbk_key_file> ] [-b <board>] [-p <option>] [-f <boardspec file>] [-e <boardspec entry>] [-d] <target_soc>

  Where:

  - ``<top>`` is the pathname of the directory that contains the PDK installation package. ``flash.sh`` is in this directory.
  - ``<pkc_key_file>`` is the RSA private key file for your Jetson carrier board. If it is a relative pathname, it is interpreted relative to the ``<top>/bootloader/`` directory.
  - ``<sbk_key_file>`` is the SBK key file for your board. It must be in the ``<top>/bootloader`` directory, or you must specify its absolute pathname. This option must used with PKC key, and currently only supports t19x.
  - ``<board>`` specifies one particular board for corresponding target_soc.
  - ``<options>`` is a string of command line options to be passed to ``flash.sh`` to generate the BUP. If the string contains whitespace characters, it must be enclosed in quotes.
  - ``<boardspec file>`` specifies a user-provided board spec file.
  - ``<boardspec entry>`` specifies a board spec entry in a user provided board spec file, such as "jetson_xavier_nx_devkit_emmc_ota_emmc_r32_7_spec" in "ota_board_specs.conf".
  - ``-d`` causes the script to run in debug mode, which keeps all boot firmware blob images in ``bootloader/signed`` and ``bootloader/multi-signed``.
  - ``<target_soc>`` is:

    - For Jetson AGX Orin series: ``t23x``
    - For Jetson Xavier NX series and AGX Xavier series: ``t19x``

Location of Generated BUP Files
###############################

Both procedures store the generated BUP(s) in the director(ies):

- For Jetson AGX Orin series: ``<top>/bootloader/payloads_t23x``
- For Jetson Xavier NX series and Jetson AGX Xavier series: ``<top>/bootloader/payloads_t19x``


Generating the Capsule Update Payload
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Starting with release 35.2, a Capsule update payload is used to implement the Bootloader update.
This section provides information about how to generate a multi-spec Capsule payload, which contains multiple
firmware binaries and BCT images of each type. The payload can be used to update any supported Jetson device.
When you start the update, UEFI uses the appropriate binary of each type for the device you are updating.


Generating a Multi-Spec Capsule Payload
#######################################

- To generate a multi-spec BUP, refer to `Generating a Multi-Spec BUP <#generating-a-multi-spec-bup>`__ for more information.

- Run the following commands to generate multi-spec Capsule payload::

     $ cd <top>
     $ sudo ./l4t_generate_soc_capsule.sh [-o <output file> [-i <input file>] [ --signer-private-cert <signer private cert> ] [ --other-public-cert <other public cert> ] [ --trusted-public-cert <trusted public cert> ] <target_soc>

  Where:

  - ``<top>`` is the pathname of the ``flash.sh`` directory, which contains the PDK installation package.
  - ``<output file>`` is the path and file name of the output Capsule image.
  - ``<input file>`` is the path and file name of the input BUP payload.
  - ``<signer private cert>`` specifies the OpenSSL signer private certificate filename. (By default, the public TestCert.pem is used.)
  - ``<other public cert>`` specifies OpenSSL other public certificate filename. (By default, the public TestSub.pub.pem is used.)
  - ``<trusted public cert>`` specifies OpenSSL trusted public certificate filename. (By default, the public TestRoot.pub.pem by default.)
  - ``<target_soc>`` is:

    - For Jetson AGX Orin series: ``t23x``
    - For Jetson Xavier NX series and AGX Xavier series: ``t19x``

Here is an example to generate a multi-spec Capsule payload for t23x::

    $ cd <top>
    $ sudo ./l4t_generate_soc_bup.sh t23x
    $ ./generate_capsule/l4t_generate_soc_capsule.sh -i bootloader/payloads_t23x/bl_only_payload -o ./TEGRA_BL.Cap t234


Manually Trigger the Capsule Update
###################################
The UEFI updates the non-current slot Bootloader when a Capsule update is triggered. The device boots from the updated non-current slot after the Capsule update has finished.

1. Copy the generated multi-spec Capsule payload to the ``EFI/UpdateCapsule`` directory in the ``esp`` partition of the active boot media.
   Refer to `Generating a Multi-Spec Capsule Payload <#generating-a-multi-spec-capsule-payload>`__ for more information.

  - For device booted from eMMC, copy the payload to the esp partition on eMMC.
  - For device booted from NVMe, copy the payload to the esp partition on NVMe.

2. Set the bit2 of the ``OsIndications`` UEFI variable.

  - For devices with QSPI flash::

       $ cd /sys/firmware/efi/efivars/
       $ printf "\x07\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" > /tmp/var_tmp.bin
       $ sudo dd if=/tmp/var_tmp.bin of=OsIndications-8be4df61-93ca-11d2-aa0d-00e098032b8c bs=12

  - For devices without QSPI flash, mount the ``esp`` partition of eMMC to set the variable::

       $ sudo mkdir -p /opt/nvidia/esp
       $ esp_uuid=$(lsblk -o name,partlabel,uuid | grep "mmcblk0" | awk '{ if($2 == "esp") print $3 }')
       $ sudo mount UUID=$esp_uuid /opt/nvidia/esp

       $ cd /opt/nvidia/esp/EFI/NVDA/Variables
       $ printf "\x07\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00" > /tmp/var_tmp.bin
       $ sudo dd if=/tmp/var_tmp.bin of=OsIndications-8be4df61-93ca-11d2-aa0d-00e098032b8c bs=12

3. Reboot the Jetson device. UEFI will use the Capsule payload to update the non-current slot Bootloader.

4. To check the ``Capsule update status``, run the ``nvbootctrl`` command::

     $ sudo nvbootctrl dump-slots-info

The output value of ``Capsule update status`` can be following::

    0 - No Capsule update
    1 - Capsule update successfully
    2 - Capsule install successfully but boot new firmware failed
    3 - Capsule install failed


Manually Sync Bootloader A/B Slots with the Capsule Update
##########################################################
Bootloader A/B slots can be synced by applying the Capsule update on a non-current slot.

If the UEFI Capsule was previously successfully updated, the current slot boots up with the image from the Capsule. To update the
non-current slot through Capsule Update, users must complete the steps below.

If the UEFI Capsule was not previously successfully updated, to ensure that  slots A and B are updated with the same image, users
must complete the following steps twice. For example, if the current slot is A, when you complete the following steps the first time,
slot B is updated. After the devices boot up from slot B, when users complete the steps again, slot A will be updated with the Capsule.
The device will now boot up from slot A.

1. Copy the Capsule payload that was used in step 1 in `Manually Trigger the Capsule Update <#manually-trigger-the-capsule-update>`__ to the
   ``EFI/UpdateCapsule`` directory in the ``esp`` partition of the active boot media.

2. Set the bit2 of the ``OsIndications`` UEFI variable.

3. Reboot the Jetson device. UEFI uses the Capsule payload to update the non-current slot Bootloader.

4. To check the Capsule update status and current slot, run the ``nvbootctrl`` command. The Capsule update status is success.
