NVIDIA Tegra
NVIDIA Tegra Linux Driver Package

Development Guide
28.3 Release


 
TX2 Bootloader Update and Redundancy
 
A/B Slot Layout
A/B System Update
Partition Selection
Update Engine
Bootloader Implementation
Partition Settings
Update Engine Usage
Enabling A/B Redundancy
Bootloader Tools
Boot Control
Bootloader Update Payload Generator
SMD Image Generator
Running the Update Engine
Update Engine State Machine
Manually Modifying Boot Slots
Sample Boot Log
Generating the Bootloader Payload Update (BUP)
The bootloader update process provides a safe bootloader update and ensures a workable bootloader partition remains on the Jetson TX2 boot storage during the update. This is achieved by keeping two sets of bootloader partitions, referred to as Slot A and Slot B, where a slot is a set of partitions that contain boot images.
Additionally, the bootloader redundancy maintains the same bootloader image on both bootloader slots; thereby allowing the system to boot from a redundant slot even if current slot is corrupted.
This A/B bootloader update process, with redundancy, prevents risks of boot failure after the bootloader update or images on current bootloader slot are corrupted.
Bootloader redundancy is disabled by default. For instructions to manually enable bootloader redundancy, consult Enabling A/B Redundancy.
A/B Slot Layout
The principle of shadow copies enables multiple placeholders. All placeholders, but one, holds backup copies. Each copy constitutes a potential 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:
Two Slot Implementation Layout
A/B System Update
The A/B slot system updates affects these components:
Partition selection
Update engine
Partition Selection
A/B system updates use two sets of partitions, referred to as slots. The system runs from the current slot, while the partitions in the unused slot are not accessed by the running system during normal operation. This approach makes updates fault resistant by keeping the unused slot as a fallback. If an error occurs during or immediately after an update, the system can roll back to the old slot and continue with a working system. To achieve this goal, partitions must be updated and cannot be used by the current slot, even if the partition includes only one copy.
Each slot has a bootable attribute that states whether the slot contains a correct system that can be used to boot the device. The current slot is bootable when the system is running, but the other slot may have an older, same, or newer version of the system. Regardless of what the current slot is, there is one slot that is the active slot; this is the slot the bootloader boots from on the next boot, or the preferred slot.
Each slot also has a successful attribute as set by the user space Update Engine (UE). The attribute is set the first time a newly updated slot boots up successfully to the kernel.
A bootable slot that was not marked as successful, after several attempts were made to boot from it, must be marked as unbootable by the bootloader. This includes changing the active slot to another bootable slot that is normally the slot running immediately before the attempt to boot into the new, active slot. The slot status details are defined in the Slot MetaData (SMD) structure as follows:
Where:
A bootable slot is the slot with a priority and a retry_count greater than 0.
A current or active slot is the slot with the highest priority, a retry_count greater than 0, and is booted from the next power cycle.
Update Engine
The A/B system updates use the update engine to prepare the system to boot into a new updated version. The update engine performs these actions:
Reads the bl_update_payload and writes data to the unused slot A/B partitions as instructed by the bootloader update payload.
Calls the boot_control interface in a pre-defined workflow.
Invokes the system reboot to reboot into the updated slot.
Updates images on other slots to keep both A and B synchronized with the new version.
For more information, see:
Update Engine Usage
Running the Update Engine
Bootloader Implementation
The A/B system uses the boot Slot MetaData (SMD) to store the slot status. It communicates between the Update Engine and the bootloader. The A/B bootloader runs the state machine to select the boot slot and handles the update failure cases as follows:
A screenshot of a cell phone Description generated with very high confidence
MB1 loads the slot metadata partition to find the current slot. If a bootable slot is not present, the device hangs. When a boot slot is found, the boot slot number, 0 or 1, along with a valid flag, is cached into scratch register 99 to be used by MB2, CBoot, or later stage loaders.
31
29
25
21
18
15
Flag
Slot A
Retry Count
Slot B
Retry Count
Maximum Slots
Current Slot Number
Magic Pattern CAFE
SCRATCH 99 Register
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
Partition Settings
All A/B partitions must be named as follows:
mb1
mb1_b
mb2
mb2_b
cboot
cboot_b
etc
The empty suffix for Slot A is to ensure backward compatibility with legacy A/B unaware partition loading mechanisms.
Update Engine Usage
The update engine, nv_update_engine, uses the Slot MetaData to instruct the bootloader what slot to boot from. The following scenarios identify all UE states.
Normal Usecase
The system is running from the current slot, either Slot A or Slot B.
No updates have been applied.
The current system slot is bootable, successful, and active slot.
In this case, the system is running from Slot B.
Slot A is the redundant slot due to a lower priority than Slot B, as follows:
Slot
Priority
retry_count
boot_successful
Slot 0
14
7
1
Slot 1
15
7
1
Update in Progress
The system is running from Slot B.
Slot B is the bootable, successful, and active slot.
Slot A was marked as unbootable because the contents of Slot A are being updated and the update is not yet complete.
A reboot in this state must continue booting from Slot B.
Slot
Priority
retry_count
boot_successful
Slot 0
0
0
0
Slot 1
15
7
1
Update Applied with a Reboot Pending
The system is running from Slot B.
Slot B is bootable, successful, but Slot A is marked as active and therefore is marked as bootable.
Slot A is not yet marked as successful and some number of attempts to boot from Slot must be made by the bootloader.
Slot
Priority
retry_count
boot_successful
Slot 0
15
7
0
Slot 1
14
7
1
System Reboot into a New Update
The system is running from Slot A for the first time.
Slot B is still bootable and successful, while Slot A is only bootable and active but not successful.
The Update Engine must mark Slot A as successful after some checks are made.
Slot
Priority
retry_count
boot_successful
Slot 0
15
6
0
Slot 1
14
7
1
Duplicate in Progress
The system is running from Slot A with a new version.
Slot B is marked as unbootable since the contents of Slot B are being updated but not yet completed.
A reboot in this state must continue booting from Slot A.
Slot
Priority
retry_count
boot_successful
Slot 0
15
6
0
Slot 1
0
0
0
Duplicate Completion
The system is running from Slot A with a new version.
Slot B was synched up with the new version.
Since Slot A, with the new version, is bootable and successful, marks Slot B as bootable and successful but with lower priority.
Slot B acts as a redundant slot.
Slot
Priority
retry_count
boot_successful
Slot 0
15
7
1
Slot 1
14
7
1
System Booted into Redundant Slot
The system is running from Slot A.
There is no update or duplicate.
Device boot must continue booting from Slot A.
However, due to data corruption or I/O errors, after failing for some number of attempts to boot from Slot A, the bootloader marks Slot A as unbootable and boots into Slot B.
Slot
Priority
retry_count
boot_successful
Slot 0
0
0
0
Slot 1
14
7
1
The update engine is limited as to what it can do during an update. Duplicates, such as the current slot, cannot be allowed until the system boots into a new version.
To maintain a robust system, the update process cannot modify the partition table, and the contents of non A/B partitions that cannot be wiped with a factory reset.
The update engine is launched under these scenarios:
1. An explicit launch by the user to update partitions with newer versions, with the command:
$ sudo nv_update_engine --install
The update engine applies the bootloader update payload (BUP) during the update. The BUP must be named bl_update_payload and must be placed under:
/opt/ota_package
2. Update Engine is launched by the boot service during a system boot with the command:
$ sudo nv_update_engine --verify
The update engine loads the slot metadata, evaluates the current state, and runs a pre-defined workflow. In normal boot, the update engine is in normal boot state, where an update is not applied and a duplicate is not required. The update engine simply exits.
Enabling A/B Redundancy
There are two methods for enabling A/B redundancy:
Creating an SMD image and setting redundancy settings.
Using the nv_update_engine tool to enable redundancy.
To enable redundancy by creating an SMD image
1. Modify the SMD configuration file smd_info.cfg to enable A/B slots.
2. Run the host tool nv_smd_generator on the x86 system to generate the SMD image with the updated SMD configuration file.
For instructions on generating the SMD image, consult SMD Image Generator.
3. Run the flash.sh script to perform a fresh flash of the device with all the partitions.
To enable redundancy by using the nv_update_engine
On the target system launch the nv_update_engine tool to enable A/B for the flashed device with A/B disabled SMD image.
For instructions consult Running the Update Engine.
Bootloader Tools
The following NVIDIA tools are provided for ease-of-use of the bootloader update process.
Boot Control
The nvbootctrl tool is intended for debugging purposes to load in the SMD image and dump the slot information. It can also be used to set the active slot to forcefully change the boot slot in the next boot.
To display the command usage
Execute the command:
$ sudo nvbootctrl
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 script that is packaged along with the flash.sh flashing script tool in the Linux for Tegra board support package.
To launch the BUP generator
Execute the command:
$ sudo [env={value}, …] ./build_l4t_bup.sh [options] <target_board> <rootdev>
Where:
<target_board> is your Linux for Tegra Jetson TX2 board.
<rootdev> is the partition where the root file system is to be flashed.
The resulting BUP is stored in the bootloader directory with the filename bl_update_payload.
Before launching the Update Engine, the BUP must be placed into the target system at:
/opt/ota_package/
For more information, see Generating the Bootloader Payload Update (BUP).
SMD Image Generator
Run the nv_smd_generator tool on X86 host systems to generate the default SMD image slot_metadata.bin that is flashed into the SMD partition.
To launch the image generator
Execute the command:
$ nv_smd_generator <config_file> <output_file>
Where:
<config_file> is the SMD configuration file.
<output_file> is the slot_metadata.bin output SMD image.
For example:
$ sudo nv_smd_generator smd_info.cfg slot_metadata.bin
In the Linux for Tegra Board Support Package, nv_smd_generator, the default SMD configuration file smd_info.cfg, and the default image file slot_metadata.bin, are installed under the directory:
<top>/bootloader
By default, the smd_info.cfg configuration file is set so that Slot A is the only available slot. This effectively disables redundancy.:
< VERSION 3 >
#
# Config 1: A/B Disabled (Default)
#
# <priority> <suffix> <retry_count> <boot_successful>
15 _a 7 1
 
#
# Config 2: A/B Enabled where A is boot slot and B is
# redundant slot
#
##< REDUNDANCY_USER 1 >
# slot info order is important!
# <priority> <suffix> <retry_count> <boot_successful>
##15 _a 7 1
##14 _b 7 1
Use Config 2: to create the SMD image and enable A/B redundancy.
To use the desired configuration
1. Add a # to comment out the configuration you wish to disable. For example, Config 1.
2. Remove the ## from the configuration you wish to enable. For example, Config 2.
Once enabled, all bootloader related partitions, the kernel partition, and the kernel-dtb partion have A/B slots. However, the user can limit A/B redundancy support for the bootloader only by setting REDUNDANCY_USER to 0.
File system redundancy support is left for the user.
Running the Update Engine
Run the update Engine script on the target system.
To enable/disable A/B redundancy
Execute this command to enable redundancy:
$ nv_update_engine --enable-ab
Execute this command to disable redundancy:
$ nv_update_engine --disable-ab
The command fails if the current boot slot is NOT 0.
To update bootloader
1. Enable A/B redundancy (a one-time command):
$ nv_update_engine --enable-ab
2. Enter superuser mode by executing the command:
$ sudo su
3. If a BUP directory does not exist, create one by executing the command:
$ mkdir /opt/ota_package
4. Copy the BUP from the host system to this newly created BUP directory with the command:
$ scp <host_loc:bl_update_payload> /opt/ota_package/
Where:
<host_loc:bl_update_payload> is where the BUP is built on the host system. You can also use a USB key to copy the BUP from the host system to the target system.
See Generating the Bootloader Payload Update for information about how to generate the BUP.
5. Launch the Update Engine to update the bootloader on the non-current slot with the command:
$ nv_update_engine --install
Update Engine State Machine
The Update Engine state machine flow is as follows:
Manually Modifying Boot Slots
NVIDIA provides the nvbootctrl tool for testing and development purposes. However, you may wish to manually change the boot slots or make modifications to the SMD partition from the userspace.
To manually modify the boot slots
1. Switch to superuser mode with this command
$ sudo su
The default password is nvidia.
2. Execute this command:
nvbootctrl <command>
The default settings are for both Slot 0 and Slot 1 as bootable, with Slot 0 having higher priority.
Where <command> is as follows:
Command
Description
get-number-slots
Printer the number of slots.
get-current-slot
Prints the currently running SLOT.
mark-boot-successful
Marks the current slot as GOOD.
set-active-boot-slot SLOT
On next boot, loads and executes SLOT.
set-slot-as-unbootable SLOT
Marks SLOT as invalid.
is-slot-bootable SLOT
Returns 0 if SLOT is bootable.
is-slot-marked-successful SLOT
Returns 0 if SLOT is marked GOOD.
get-suffix SLOT
Prints the suffix for the SLOT.
dump-slots-info
Prints the information for the slots.
SLOT is the zero-based slot number.
To show the current boot slot
Execute this command:
root@tegra-ubuntu:/home/nvidia# nvbootctrl get-current-slot
0
root@tegra-ubuntu:/home/nvidia#
To show the slot status
Execute one of the following commands:
Before enabling A/B redundancy:
root@tegra-ubuntu:/home/nvidia# nvbootctrl dump-slots-info
magic:0x43424e00, version: 3 features: 0 num_slots: 1
slot: 0, priority: 15, suffix: _a, retry_count: 7, boot_successful: 1
slot: 1, priority: 0, suffix: , retry_count: 0, boot_successful: 0
root@tegra-ubuntu:/home/nvidia#
After enabling A/B redundancy:
root@tegra-ubuntu:/home/nvidia# nvbootctrl dump-slots-info magic:0x43424e00, version: 3 features: 3 num_slots: 2
slot: 0, priority: 15, suffix: _a, retry_count: 7, boot_successful: 1
slot: 1, priority: 14, suffix: _b, retry_count: 7, boot_successful: 1
root@tegra-ubuntu:/home/nvidia#
Sample Boot Log
The boot slot is selected by MB1. The following sample log shows that Slot 1 is selected as the boot slot. The message displayed from MB1 is available from a debug build of MB1 that has messages enabled. Messages from MB2 are always available.
[0000.040] I> Welcome to MB1-coldboot(dev-version : 14.00.170822-t186-M-00.00-96e265a3)
[0000.048] I> rst_source : 0xb
[0000.051] I> rst_level : 0x1
[0000.053] I> Read lock all AES keyslots
[0000.057] I> Read lock all RSA keyslots
[0000.061] I> Clear SE keyslots left open by BR
[0000.065] I> Last mts-fallback status: 0x00000000
[0000.070] I> Boot-device: eMMC
[0000.094] I> sdmmc ddr50 mode
[0000.098] I> A/B: bin_type (19) slot 0
[0000.102] I> Binary(19) of size 512 is loaded @ 0x40043400
[0000.108] I> Boot chain chosen: 1
[0000.111] I> Boot chain chosen: 1
[0000.114] I> magic:0x43424e00, version: 259, num_slots: 2
[0000.119] I> slot: 0, pri: 14, suffix: _a, retry: 7, boot_succ: 1
[0000.125] I> slot: 1, pri: 15, suffix: _b, retry: 6, boot_succ: 1
[0000.131] I> Loading MB1-BCT to SysRAM
[0000.135] I> A/B: bin_type (0) slot 1
[0000.138] I> Boot-device: eMMC
. . .
. . .
[0000.888] I> Welcome to MB2(TBoot-BPMP)(version: 01.00.160913-t186-M-00.00-mobile-09b4fbd4)
[0000.897] I> Default Heap @ [0xd486400 - 0xd488400]
[0000.901] I> DMA Heap @ [0x84a00000 - 0x85300000]
[0000.906] I> bit @ 0xd480000
[0000.909] I> BR-BCT relocated to 0xd7020000
[0000.913] I> Boot-device: eMMC
[0000.917] I> sdmmc bdev is already initialized
[0000.922] I> pmic: reset reason (nverc) : 0x0
[0000.926] I> Reading GPT from 512 for device 00000003
[0000.932] I> Reading GPT from 8388096 for device 00000003
[0000.939] I> Found 13 partitions in 00000003 device
[0000.944] I> Reading GPT from 512 for device 00010003
[0000.950] I> Found 27 partitions in 00010003 device
[0000.956] I> A/B: bin_type (16) slot 1
[0000.959] I> Loading partition bpmp-fw_b at 0xd7800000
[0000.964] I> Reading two headers - addr:0xd7800000 blocks:1
[0000.970] I> Addr: 0xd7800000, start-block: 58762425, num_blocks: 1
[0000.985] I> Binary(16) of size 528848 is loaded @ 0xd7800000
. . .
. . .
Generating the Bootloader Payload Update (BUP)
Use these procedures as examples to generate the bootloader payload update.
To generate the BUP
Execute these commands to create the BUP image with the indicated FAB/BOARDID/FUSELEVEL Jetson TX2 board:
$ cd <top>
$ sudo FAB=B00 BOARDID=3310 FUSELEVEL=fuselevel_production ./build_l4t_bup.sh jetson-tx2 mmcblk0p1
Execute these commands to create the BUP image for the board connected to the host system:
1. Place the target board into force recovery mode.
2. Enter the following commands:
$ cd <top>
$ sudo ./build_l4t_bup.sh jetson-tx2 mmcblk0p1
Execute these commands to create the PKC signed BUP image for the indicated FAB/BOARDID/FUSELEVEL Jetson TX2 board:
$ cd <top>
$ sudo FAB=B00 BOARDID=3310 FUSELEVEL=fuselevel_production ./build_l4t_bup.sh -s <pkc_key_file> jetson-tx2 mmcblk0p1
Where:
<top> is the location of the parent directory of the PDK installation package, where flash.sh command is located.
<pkc_key_file> is the RSA private key file for your board. It must be located under the <top>/bootloader directory or be specified by a complete (absolute) pathname.
Execute these commands to create the PKC signed BUP image for the board connected to the host system:
1. Place the target board into force recovery mode.
2. Enter the following commands:
$ cd <top>
$ sudo ./build_l4t_bup.sh -s <pkc_key_file> -u <pkc_key_file> jetson-tx2 mmcblk0p1
Where:
<top> is the location to parent directory of the PDK installation package, where the flash.sh command is located.
<pkc_key_file> is the RSA private key file for your board. It must be located under <top>/bootloader directory or a complete (absolute) pathname.