[TOC]
System Module
Android BCB
BCB (Bootloader Control Block) is a mechanism designed by Android to interact with the bootloader to control the system boot flow. The data structure is defined at offset 16KB or position 0 of the misc partition.
Data structure:
struct android_bootloader_message {
char command[32];
char status[32];
char recovery[768];
/* The 'recovery' field used to be 1024 bytes. It has only ever
* been used to store the recovery command line, so 768 bytes
* should be plenty. We carve off the last 256 bytes to store the
* stage string (for multistage packages) and possible future
* expansion. */
char stage[32];
/* The 'reserved' field used to be 224 bytes when it was initially
* carved off from the 1024-byte recovery field. Bump it up to
* 1184-byte so that the entire bootloader_message struct rounds up
* to 2048-byte. */
char reserved[1184];
};
command: Boot command, currently supports the following three:
| Parameter | Function |
|---|---|
| bootonce-bootloader | Boot into U-Boot fastboot |
| boot-recovery | Boot into recovery |
| boot-fastboot | Boot into recovery fastboot (abbreviated as fastbootd) |
recovery: The accompanying command for entering recovery mode, starts with "recovery\n", followed by multiple parameters starting with "--" and ending with "\n", e.g., "recovery\n--wipe_ab\n--wipe_package_size=345\n--reason=wipePackage\n":
| Parameter | Function |
|---|---|
| update_package | OTA upgrade |
| retry_count | Number of recovery upgrade attempts, e.g., if power is lost unexpectedly during upgrade, re-enter recovery based on this value |
| wipe_data | erase user data (and cache), then reboot |
| wipe_cache | wipe cache (but not user data), then reboot |
| show_text | show the recovery text menu, used by some bootloader |
| sideload | |
| sideload_auto_reboot | an option only available in user-debug build, reboot the device without waiting |
| just_exit | do nothing, exit and reboot |
| locale | save the locale to cache, then recovery will load locale from cache when reboot |
| shutdown_after | return shutdown |
| wipe_all | Erase the entire userdata partition |
| wipe_ab | wipe the current A/B device, with a secure wipe of all the partitions in RECOVERY_WIPE |
| wipe_package_size | wipe package size |
| prompt_and_wipe_data | prompt the user that data is corrupt, with their consent erase user data (and cache), then reboot |
| fw_update | SD card firmware upgrade |
| factory_mode | Factory mode, mainly used for device testing, such as PCBA testing |
| pcba_test | Enter PCBA testing |
| resize_partition | Repartition size, supported by Android Q dynamic partitions |
| rk_fwupdate | Specify RK SD/USB firmware upgrade, scope limited to U-Boot |
The U-Boot phase generally does not need to use or pay attention to the above parameters; they are provided for user learning reference.
AArch32
ARMv8 64-bit chips support downgrading from AArch64 to AArch32 mode (compatible with ARMv7), and the code must be compiled with 32-bit.
Users can use this macro to confirm whether it is currently ARMv8 AArch32 mode:
CONFIG_ARM64_BOOT_AARCH32=y
DTBO/DTO
To facilitate user understanding of this section, please first read the appendix chapter to clarify the terminology: DTB, DTBO, DTC, DTO, DTS, FDT.
The relationship between them can be described as:
- DTS is a file used to describe FDT.
- DTS can be compiled by DTC to generate DTB/DTBO.
- DTB and DTBO can be merged into a new DTB through DTO operations.
Usually, many users are accustomed to using "DTBO" to replace the action meaning of "DTO". In the following text, we avoid this conceptual confusion and clarify: DTO is a verb concept representing an operation; DTBO is a noun concept referring to the secondary dtb used for overlay.
For more knowledge in this section, please refer to: https://source.android.google.cn/devices/architecture/dto.
Principle Introduction
DTO (Device Tree Overlay) is a function introduced and mandatory after Android P. It allows a secondary device tree Blob (DTBO) to be overlaid on an existing main device tree Blob. DTO can maintain the SoC device tree and dynamically overlay device trees specific to a particular device, thereby adding nodes to the tree and making changes to properties in the existing tree.
The main device tree Blob (.dtb) is generally provided by the Vendor manufacturer, while the secondary device tree Blob (.dtbo) can be provided by ODM/OEM and other manufacturers. They are finally merged by the bootloader before being passed to the kernel. As shown below:

Image source: https://source.android.google.cn/devices/architecture/dto
Note: The compilation of DTB and DTBO used for DTO operations differs from ordinary DTB compilation, with special syntax differences:
When compiling .dts with dtc, you must add the option -@ to add the _symbols_ node in the generated .dtbo. The _symbols_ node contains a list of all nodes with labels, which can be used as a reference by the DTO library. Example:
- Example command for compiling the main .dts:
dtc -@ -O dtb -o my_main_dt.dtb my_main_dt.dts
- Example command for compiling the overlay DT
.dts:
dtc -@ -O dtb -o my_overlay_dt.dtbo my_overlay_dt.dts
DTO Enable
- Configuration enable:
CONFIG_CMD_DTIMG=y
CONFIG_OF_LIBFDT_OVERLAY=y
- Implementation of the board_select_fdt_index() function. This is a __weak function; users can re-implement it according to actual needs. The function selects the DTBO for DTO operation from multiple DTBOs (returns the index, starting from 0). The default weak function returns index 0.
/*
* Default return index 0.
*/
__weak int board_select_fdt_index(ulong dt_table_hdr)
{
/*
* User can use "dt_for_each_entry(entry, hdr, idx)" to iterate
* over all dt entry of DT image and pick up which they want.
*
* Example:
* struct dt_table_entry *entry;
* int index;
*
* dt_for_each_entry(entry, dt_table_hdr, index) {
*
* .... (use entry)
* }
*
* return index;
*/
return 0;
}
DTO Result
- After DTO execution completes, the result can be seen in the U-Boot boot information:
// Successful print
ANDROID: fdt overlay OK
// Failed print
ANDROID: fdt overlay failed, ret=-19
The cause of failure is usually incompatibility between the content of the main/secondary device tree blobs. Therefore, users need to be clear about their generation syntax and compatibility.
- After successful DTO execution, the following information is appended to the kernel's cmdline, indicating which DTBO was used for the DTO operation:
androidboot.dtbo_idx=1 // idx starts from 0, indicating DTBO with idx=1 was selected for DTO operation
- After successful DTO execution, users can use the
fdtcommand in the U-Boot command line to view the DTB content and confirm whether the changes have taken effect.
Cmdline
cmdline is an important means for U-Boot to pass parameters to the kernel, such as boot storage, device status, etc. Currently, cmdline parameters come from multiple sources. U-Boot concatenates and filters duplicate data before passing them to the kernel. The cmdline in the U-Boot phase is stored in the bootargs environment variable.
U-Boot ultimately implements cmdline passing by modifying the /chosen/bootargs in the kernel DTB.
Data Sources
-
parameter.txt file
If using the RK format partition table, cmdline information can be stored in parameter.txt, for example:
CMDLINE: console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),If using the GPT format partition table, storing cmdline information in parameter.txt is invalid.
-
kernel dts's
/chosen/bootargs, for example:chosen {bootargs = "earlyprintk=uart8250,mmio32,0xff30000 swiotlb=1 console=ttyFIQ0androidboot.baseband=N/A androidboot.veritymode=enforcingandroidboot.hardware=rk30board androidboot.console=ttyFIQ0init=/init kpti=0";}; -
U-Boot: Based on the current running state, U-Boot dynamically appends some content to cmdline. For example:
storagemedia=emmc androidboot.mode=emmc ...... -
The boot/recovery.img firmware header usually also has cmdline field information.
Data Meanings
The following lists the meanings of commonly used cmdline parameters on the RK platform. For more information, refer to the kernel documentation: Documentation/admin-guide/kernel-parameters.txt.
-
sdfwupdate: SD upgrade card flag, required by the recovery program.
-
root=PARTUUID: Specifies the UUID of the rootfs(system) partition, only supported with GPT table.
-
skip_initramfs: Kernel does not use the ramdisk loaded by uboot but uses the ramdisk in rootfs(system).
-
storagemedia: Storage boot type.
-
console: Kernel print port configuration information.
-
earlycon: Specifies the serial port and its configuration before the serial port node is established.
-
loop.max_part: max_part is used to set the number of partitions each loop device can support.
-
rootwait: Used when the filesystem is not immediately available, e.g., emmc initialization is not complete. If root_wait is not set, mount rootfs will fail. Adding this parameter allows waiting for the driver to load, then copying rootfs from the storage device before mounting, thus avoiding failure.
-
ro/rw: Attributes for loading rootfs, read-only/read-write.
-
firmware_class.path: Specifies the driver location, such as wifi, bt, gpu, etc.
-
dm="lroot none 0, 0 4096 linear 98:3 0, 4096 4096 linear 98:32" root=/dev/dm-0: Boot to a rw dm-linear target of 8192 sectors split across two block devices identified by their major:minor numbers. After boot, udev will rename this target to /dev/mapper/lroot (depending on the rules). No uuid was assigned. Reference: https://android.googlesource.com/kernel/common/+/android-3.18/Documentation/device-mapper/boot.txt
-
androidboot.slot_suffix: Specifies which slot to boot from for AB System.
-
androidboot.serialno: Provides serial number for kernel and upper layers, e.g., adb serial number, etc.
-
androidboot.verifiedbootstate: Android requirement, provides the state of uboot verified firmware for upper layers. Three states:
- green: If in LOCKED state and the key used for verification was not set by the end user.
- yellow: If in LOCKED state and the key used for verification was set by the end user.
- orange: If in the UNLOCKED state.
-
androidboot.hardware: Boot device, e.g., rk30board.
-
androidboot.verifymode: Specifies the real mode/state of the verified partition (i.e., verify firmware integrity).
-
androidboot.selinux: SELinux is a mandatory access control (MAC) security system based on the domain-type model. Three modes:
- enforcing: Enforcing mode, represents SELinux is running and has correctly started restricting domain/type.
- permissive: Permissive mode: represents SELinux is running but only warning messages are issued without actually restricting domain/type access. This mode can be used for SELinux debugging.
- disabled: Disabled, SELinux is not actually running.
-
androidboot.mode: Android boot mode, includes normal and charger.
- normal: Normal boot.
- charger: Power on after shutdown with power connected, androidboot.mode is set to charger. This value is set by uboot into the bootargs environment variable after detecting power charging.
-
androidboot.wificountrycode: Sets wifi country code, e.g., US, CN.
-
androidboot.baseband: Configures baseband, RK does not have this function, set to N/A.
-
androidboot.console: Android information output port configuration.
-
androidboot.vbmeta.device=PARTUUID: Specifies the location of vbmeta in storage.
-
androidboot.vbmeta.hash_alg: Sets vbmeta hash algorithm, e.g., sha512.
-
androidboot.vbmeta.size: Specifies the size of vbmeta.
-
androidboot.vbmeta.digest: Passes the digest of vbmeta to the kernel. The kernel calculates the digest after loading vbmeta and compares it with this digest.
-
androidboot.vbmeta.device_state: avb2.0 specifies system lock and unlock.
ENV Operations
Framework Support
ENV is a very important data management method in the U-Boot framework. It builds a mapping between "key-value" and "data" through a hash table, supporting "add/delete/modify/query" operations. Usually, we collectively refer to the managed key-value pairs and data as: environment variables. U-Boot supports saving ENV data on various storage media: NOWHERE/eMMC/FLASH/EEPROM/NAND/SPI_FLASH/UBI...
Configuration:
// Default configuration: ENV is saved in memory
CONFIG_ENV_IS_NOWHERE
// ENV is saved on various storage media
CONFIG_ENV_IS_IN_MMC
CONFIG_ENV_IS_IN_NAND
CONFIG_ENV_IS_IN_EEPROM
CONFIG_ENV_IS_IN_FAT
CONFIG_ENV_IS_IN_FLASH
CONFIG_ENV_IS_IN_NVRAM
CONFIG_ENV_IS_IN_ONENAND
CONFIG_ENV_IS_IN_REMOTE
CONFIG_ENV_IS_IN_SPI_FLASH
CONFIG_ENV_IS_IN_UBI
// Any storage medium connected to the BLK framework layer (except mmc), recommended by RK platform!
CONFIG_ENV_IS_IN_BLK_DEV
Framework code:
./env/nowhere.c
./env/env_blk.c
./env/mmc.c
./env/nand.c
./env/eeprom.c
./env/embedded.c
./env/ext4.c
./env/fat.c
./env/flash.c
......
Related Interfaces
// Get environment variable
char *env_get(const char *varname);
ulong env_get_ulong(const char *name, int base, ulong default_val);
ulong env_get_hex(const char *varname, ulong default_val);
// Modify or create environment variable, setting value to NULL is equivalent to deletion
int env_set(const char *varname, const char *value);
int env_set_ulong(const char *varname, ulong value);
int env_set_hex(const char *varname, ulong value);
// Load all ENV information from the storage medium
int env_load(void);
// Save all current ENV information to the storage medium
int env_save(void);
- env_load(): Users do not need to call it; the U-Boot framework will call it at the appropriate point in the boot flow.
- env_save(): Users actively call it when needed; it saves all ENV information to the storage medium specified by CONFIG_ENV_IS_NOWHERE_XXX.
Advanced Interfaces
RK provides two unified advanced interfaces for handling ENV, with create, append, and replace functions. They are mainly designed to handle the bootargs environment variable but are also applicable to other environment variable operations.
/**
* env_update() - update sub value of an environment variable
*
* This add/append/replace the sub value of an environment variable.
*
* @varname: Variable to adjust
* @varvalue: Value to add/append/replace
* @return 0 if OK, 1 on error
*/
int env_update(const char *varname, const char *varvalue);
/**
* env_update_filter() - update sub value of an environment variable but
* ignore some key word
*
* This add/append/replace/ignore the sub value of an environment variable.
*
* @varname: Variable to adjust
* @varvalue: Value to add/append/replace
* @ignore: Value to be ignored that in varvalue
* @return 0 if OK, 1 on error
*/
int env_update_filter(const char *varname, const char *varvalue, const char *ignore);
1 env_update() usage rules:
- Create: If varname does not exist, create varname and varvalue.
- Append: If varname exists but varvalue does not exist in it, append varvalue.
- Replace: If varname exists and varvalue exists in it, replace the old one with the current varvalue. For example: originally "storagemedia=emmc" exists, currently passed varvalue is "storagemedia=rknand", then it is updated to "storagemedia=rknand".
2 env_update_filter() is an extended version of env_update(): It removes a specified keyword from varvalue while updating env.
3 Note: env_update() and env_update_filter() both use spaces and "=" as delimiters to split ENV content. Therefore, the operation units are: single words, "key=value" combined words.
- Single word: sdfwupdate, ...
- "key=value" combined words: storagemedia=emmc, init=/init, androidboot.console=ttyFIQ0, ...
- The above two interfaces cannot handle long string units. For example, they cannot operate on "console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive" as a single unit.
Storage Location
env_save() can save ENV to the storage medium. The storage location and size of ENV on the RK platform are defined as follows:
if ARCH_ROCKCHIP
config ENV_OFFSET
hex
depends on !ENV_IS_IN_UBI
depends on !ENV_IS_NOWHERE
default 0x3f8000
help
Offset from the start of the device (or partition)
config ENV_SIZE
hex
default 0x8000
help
Size of the environment storage area
endif
- Generally, ENV_OFFSET and ENV_SIZE are not recommended to be modified.
General Options
Commonly used storage media generally include: eMMC/sdmmc/Nandflash/Norflash, etc. However, native U-Boot Nand and Nor ENV drivers all use the MTD framework, while all supported storage on RK uses the BLK framework layer. Therefore, these ENV drivers cannot be used.
To this end, RK provides the CONFIG_ENV_IS_IN_BLK_DEV configuration option for storage connected to the BLK framework layer:
- For eMMC/sdmmc, still choose CONFIG_ENV_IS_IN_MMC.
- For Nand and Nor, you can choose CONFIG_ENV_IS_IN_BLK_DEV.
Please read the definition of CONFIG_ENV_IS_IN_BLK_DEV in Kconfig before use.
// Already specified by default, no modification needed
CONFIG_ENV_OFFSET
CONFIG_ENV_SIZE
// Usually not needed
CONFIG_ENV_OFFSET_REDUND (optional)
CONFIG_ENV_SIZE_REDUND (optional)
CONFIG_SYS_MMC_ENV_PART (optional)
Note: Regardless of which CONFIG_ENV_IS_IN_XXX configuration is chosen, please first read the definition description in Kconfig, which contains sub-configuration instructions.
fw_printenv Tool
fw_printenv is an ENV tool provided by U-Boot for use in Linux. Through this tool, users can access and modify ENV content on Linux. Using this tool requires that the ENV area is located on a partition visible to the kernel (an independent partition is recommended). Essentially, it accesses the ENV area through the kernel's sys storage node.
Tool acquisition method:
./make.sh env
After executing the command, you get:
./tools/env/fw_printenv // ENV read/write tool
./tools/env/fw_env.config // ENV configuration file
./tools/env/README // ENV read/write tool documentation
Please refer to the README document for usage.
HW-ID DTB
U-Boot on the RK platform supports dynamically loading different Kernel DTBs by detecting GPIO or ADC states on the hardware, tentatively called HW-ID DTB (Hardware id DTB) function.
Design Principle
Hardware designs often update versions and some components, such as screens, wifi modules, etc. If every hardware version requires a corresponding software set, maintenance becomes troublesome. Therefore, the HW_ID function is needed to allow one set of software to adapt to different hardware versions.
For different hardware versions, the software needs to provide corresponding dtb files, as well as ADC/GPIO hardware unique values to represent the current hardware version (e.g., fixed adc value, fixed GPIO level).
Users package all dtb files corresponding to hardware versions into the same resource.img. U-Boot detects the hardware unique value when booting the kernel and finds the dtb matching the current hardware version from resource.img to pass to the kernel.
Hardware Reference
Currently supports ADC and GPIO methods to determine the hardware version.
ADC Reference Design
The RK3326-EVB/PX30-EVB main board has reserved voltage divider resistors. Different resistor divisions yield different ADC values, allowing determination of different hardware versions:

The matching MIPI screen board has another pulldown resistor reserved:

Different MIPI screens are configured with different resistance values, and together with the EVB main board, a unique ADC parameter value is determined.
Current V1 version ADC calculation method: The maximum ADC parameter is 1024, corresponding to the ADC_IN0 pin being directly pulled up to the supply voltage of 1.8V. The MIPI screen has a 10K pulldown resistor. When connected to the EVB board, ADC = 1024 * 10K / (10K + 51K) = 167.8.
GPIO Reference Design
Currently there is no GPIO hardware reference design; users can customize it themselves.
DTB Naming
Users need to reflect the ADC/GPIO hardware unique value information in the dtb file name. Naming rules are as follows:
ADC as HW_ID DTB:
-
File name ends with ".dtb".
-
HW_ID format: #[controller]_ch[channel]=[adcval], called a complete unit.
[controller]: ADC controller node name in dts. [channel]: ADC channel. [adcval]: ADC center value, actual valid range is adcval+-30.
-
Each complete unit must use lowercase letters, no spaces inside.
-
Multiple units are separated by #, supporting up to 10 units.
Examples:
rk3326-evb-lp3-v10#saradc_ch2=111#saradc_ch1=810.dtb
rk3326-evb-lp3-v10#_saradc_ch2=569.dtb
GPIO as HW_ID DTB:
-
File name ends with ".dtb".
-
HW_ID format: #gpio[pin]=[level], called a complete unit.
[pin]: GPIO pin, e.g., 0a2 represents gpio0a2. [level]: GPIO pin level.
-
Each complete unit must use lowercase letters, no spaces inside.
-
Multiple units are separated by #, supporting up to 10 units.
Examples:
rk3326-evb-lp3-v10#gpio0a2=0#gpio0c3=1.dtb
DTB Packaging
Kernel repository: scripts/mkmultidtb.py. This script can package multiple dtbs into the same resource.img.
Users need to open the script file and write the dtb files to be packaged into the DTBS dictionary, filling in the corresponding ADC/GPIO configuration information.
...
DTBS = {}
DTBS['PX30-EVB'] = OrderedDict([('rk3326-evb-lp3-v10', '#_saradc_ch0=166'),
('px30-evb-ddr3-lvds-v10', '#_saradc_ch0=512')])
...
In the above example, executing scripts/mkmultidtb.py PX30-EVB will generate a resource.img containing 3 dtbs:
- rk-kernel.dtb: RK default dtb, not shown in the above dictionary. Used by default when no dtb matches. The packaging script uses the first dtb in DTBS as the default dtb.
- rk3326-evb-lp3-v10#_saradc_ch0=166.dtb: rk3326 dtb file containing ADC information.
- px30-evb-ddr3-lvds-v10#_saradc_ch0=512.dtb: px30 dtb file containing ADC information.
Function Enable
Configuration option:
CONFIG_ROCKCHIP_HWID_DTB=y
Driver code:
./arch/arm/mach-rockchip/resource_img.c // Specific implementation: rockchip_read_hwid_dtb()
DTS configuration:
If using GPIO for hardware identification, the corresponding pinctrl and gpio nodes must be preserved in rkxx-u-boot.dtsi; ADC is enabled by default.
For example: gpio0 and gpio1 for identification:
...
&pinctrl {
u-boot,dm-spl; // Add this attribute to keep the node in the U-Boot DTB. Same below.
};
&gpio0 {
u-boot,dm-spl;
};
&gpio1 {
u-boot,dm-spl;
};
...
Loading Result
......
mmc0(part 0) is current device
boot mode: None
DTB: rk3326-evb-lp3-v10#_saradc_ch0=166.dtb // Print matched DTB, otherwise default "rk-kernel.dtb"
Using kernel dtb
......
AB System
The so-called A/B System divides the system firmware into two sets, called slot-a and slot-b. The system can boot from either slot. When one slot fails to boot, it can still boot from the other. During upgrades, the firmware can be directly copied to the other slot without entering system upgrade mode. For detailed principles and flow, please refer to the Advanced Principles chapter.
Currently, both the pre-loader and U-Boot on the RK platform support the A/B system.
Chip Support
| Chip | Android Support | Linux Support |
|---|---|---|
| rk3128x | N | Y |
| rk3126 | N | Y |
| rk322x | Y | Y |
| rk3288 | N | Y |
| rk3368 | N | Y |
| rk3328 | N | Y |
| rk3399 | N | Y |
| rk3308 | N | Y |
| px30 | Y | Y |
| rk3326 | Y | Y |
Configuration Items
A/B System depends on LIBAVB, as follows:
// Libraries A/B depends on
CONFIG_AVB_LIBAVB=y
CONFIG_AVB_LIBAVB_AB=y
CONFIG_AVB_LIBAVB_ATX=y
CONFIG_AVB_LIBAVB_USER=y
CONFIG_RK_AVB_LIBAVB_USER=y
// Enable A/B function
CONFIG_ANDROID_AB=y
Partition Table
A/B System has requirements for the partition table: partitions that need to support A/B must have suffixes _a and _b. Reference parameter.txt:
FIRMWARE_VER:8.1
MACHINE_MODEL:RK3326
MACHINE_ID:007
MANUFACTURER: RK3326
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: 3326
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot_a),0x00002000@0x00006000(uboot_b),0x00002000@0x00008000(trust_a),0x00002000@0x0000a000(trust_b),0x00001000@0x0000c000(misc),0x00001000@0x0000d000(vbmeta_a),0x00001000@0x0000e000(vbmeta_b),0x00020000@0x0000e000(boot_a),0x00020000@0x0002e000(boot_b),0x00100000@0x0004e000(system_a),0x00300000@0x0032e000(system_b),0x00100000@0x0062e000(vendor_a),0x00100000@0x0072e000(vendor_b),0x00002000@0x0082e000(oem_a),0x00002000@0x00830000(oem_b),0x0010000@0x00832000(factory),0x00008000@0x842000(factory_bootloader),0x00080000@0x008ca000(oem),-@0x0094a000(userdata)
Precautions
After enabling the A/B system on old U-Boot, if users access partitions with a/b suffixes, the partition name passed to part_get_info_by_name() must include the slot suffix, e.g., "boot_a" or "boot_b". This adds a lot of redundant code: users must first obtain the current system slot, then perform string concatenation to get the partition name.
The new code optimizes this issue. If the user's code version is after the following commit, accessing a/b partitions can include or omit the slot suffix; the framework layer will automatically detect which slot the current system is using. For example: users can directly use "boot".
commit c6666740ee3b51c3e102bfbaf1ab95b78df29246
Author: Joseph Chen <chenjh@rock-chips.com>
Date: Thu Oct 24 15:48:46 2019 +0800
common: android/rkimg: remove/clean android a/b (slot) code
- the partition disk layer takes over the responsibility of slot suffix
appending, we remove relative code to make file clean;
- put android a/b code together and name them to be easily understood,
this makes file easy to read.
Change-Id: Id8c838da682ce6098bd7192d7d7c64269f4e86ba
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
AVB Secure Boot
AVB stands for Android Verified Boot, a set of firmware verification processes designed by Google, mainly used to verify boot, system, and other firmware. Rockchip Secure Boot implements a complete Secure Boot verification solution by combining the verification method from communication with AVB.
Features
- Security verification
- Integrity verification
- Anti-rollback protection
- Persistent partition support
- Chained partitions support, can be consistent with the boot/system signing private key, or the oem can keep the private key, but must be signed by PRK.
Configuration
Enabling AVB requires trust support:
CONFIG_OPTEE_CLIENT=y
CONFIG_OPTEE_V1=y
CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y // Secure data stored in security partition
CONFIG_OPTEE_V1: Applicable platforms: 312x, 322x, 3288, 3228H, 3368, 3399.CONFIG_OPTEE_V2: Applicable platforms: 3326, 3308.CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION: Only enable this macro when eMMC rpmb cannot be used, not enabled by default.
Enable AVB-related configurations:
CONFIG_AVB_LIBAVB=y
CONFIG_AVB_LIBAVB_AB=y
CONFIG_AVB_LIBAVB_ATX=y
CONFIG_AVB_LIBAVB_USER=y
CONFIG_RK_AVB_LIBAVB_USER=y
// The above are required, the following support AVB and A/B features, which can be used separately.
CONFIG_ANDROID_AB=y // This supports A/B
CONFIG_ANDROID_AVB=y // This supports AVB
// The following macro is for platforms with efuse only
CONFIG_ROCKCHIP_PRELOADER_PUB_KEY=y
// The following macro needs to be enabled for strict unlock verification
CONFIG_RK_AVB_LIBAVB_ENABLE_ATH_UNLOCK=y
// Enable security verification
CONFIG_AVB_VBMETA_PUBLIC_KEY_VALIDATE=y
// If cpuid is needed as challenge number, enable the following macros
CONFIG_MISC=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_ROCKCHIP_OTP=y
Reference
Because AVB involves a lot of content, please refer to the Advanced Principles chapter for other principles and configurations.
Fastboot
Fastboot is a method provided by Android to interact with U-Boot via USB, generally used for obtaining device information, flashing firmware, etc.
Configuration Options
// Enable configuration
CONFIG_FASTBOOT
CONFIG_FASTBOOT_FLASH
CONFIG_USB_FUNCTION_FASTBOOT
// Parameter configuration
CONFIG_FASTBOOT_BUF_ADDR
CONFIG_FASTBOOT_BUF_SIZE
CONFIG_FASTBOOT_FLASH_MMC_DEV
CONFIG_FASTBOOT_USB_DEV
Trigger Methods
Fastboot uses Google adb's VID/PID by default. There are several trigger methods:
- Execute in kernel command line: reboot fastboot
- Execute in U-Boot command line: fastboot usb 0
- Press and hold key combination during boot: ctrl+f
Commands Supported
fastboot flash < partition > [ < filename > ]
fastboot erase < partition >
fastboot getvar < variable > | all
fastboot set_active < slot >
fastboot reboot
fastboot reboot-bootloader
fastboot flashing unlock
fastboot flashing lock
fastboot stage [ < filename > ]
fastboot get_staged [ < filename > ]
fastboot oem fuse at-perm-attr-data
fastboot oem fuse at-perm-attr
fastboot oem at-get-ca-request
fastboot oem at-set-ca-response
fastboot oem at-lock-vboot
fastboot oem at-unlock-vboot
fastboot oem at-disable-unlock-vboot
fastboot oem fuse at-bootloader-vboot-key
fastboot oem format
fastboot oem at-get-vboot-unlock-challenge
fastboot oem at-reset-rollback-index
Command Details
-
fastboot flash < partition > [ < filename > ]
Function: Partition flashing
Example: fastboot flash boot boot.img
-
fastboot erase < partition >
Function: Erase partition
Example: fastboot erase boot
-
fastboot getvar < variable >
Function: Get device information
Example: fastboot getvar version-bootloader
< variable > parameters:
version /* fastboot version */version-bootloader /* uboot version */version-basebandproduct /* Product information */serialno /* Serial number */secure /* Whether security verification is enabled */max-download-size /* Maximum bytes per transfer supported by fastboot */logical-block-size /* Logical block size */erase-block-size /* Erase block size */partition-type : < partition > /* Partition type */partition-size : < partition > /* Partition size */unlocked /* Device lock state */off-mode-chargebattery-voltagevariantbattery-soc-okslot-count /* Number of slots */has-slot: < partition > /* Check if the partition name exists in the slot */current-slot /* Currently booted slot */slot-suffixes /* Slots the current device has, prints their name */slot-successful: < _a | _b > /* Check if the partition has been successfully verified and booted */slot-unbootable: < _a | _b > /* Check if the partition is set to unbootable */slot-retry-count: < _a | _b > /* Check the retry-count of the partition */at-attest-dhat-attest-uuidat-vboot-state -
fastboot getvar all
Function: Get all device information
-
fastboot set_active < slot >
Function: Set the slot to boot from
Example: fastboot set_active _a
-
fastboot reboot
Function: Reboot device, normal boot
Example: fastboot reboot
-
fastboot reboot-bootloader
Function: Reboot device, enter fastboot mode
Example: fastboot reboot-bootloader
-
fastboot flashing unlock
Function: Unlock device, allow firmware flashing
Example: fastboot flashing unlock
-
fastboot flashing lock
Function: Lock device, prohibit flashing
Example: fastboot flashing lock
-
fastboot stage [ < filename > ]
Function: Download data to device memory, memory start address is CONFIG_FASTBOOT_BUF_ADDR
Example: fastboot stage permanent_attributes.bin
-
fastboot get_staged [ < filename > ]
Function: Get data from device
Example: fastboot get_staged raw_unlock_challenge.bin
-
fastboot oem fuse at-perm-attr
Function: Burn permanent_attributes.bin and hash
Example: fastboot stage permanent_attributes.bin fastboot oem fuse at-perm-attr
-
fastboot oem fuse at-perm-attr-data
Function: Only burn permanent_attributes.bin to secure storage area (RPMB)
Example: fastboot stage permanent_attributes.bin fastboot oem fuse at-perm-attr-data
-
fastboot oem at-get-ca-request
-
fastboot oem at-set-ca-response
-
fastboot oem at-lock-vboot
Function: Lock device
Example: fastboot oem at-lock-vboot
-
fastboot oem at-unlock-vboot
Function: Unlock device, currently supports authenticated unlock
Example: fastboot oem at-get-vboot-unlock-challenge fastboot get_staged raw_unlock_challenge.bin ./make_unlock.sh (see make_unlock.sh reference) fastboot stage unlock_credential.bin fastboot oem at-unlock-vboot
Refer to "how-to-generate-keys-about-avb.md"
-
fastboot oem fuse at-bootloader-vboot-key
Function: Burn bootloader key hash
Example: fastboot stage bootloader-pub-key.bin fastboot oem fuse at-bootloader-vboot-key
-
fastboot oem format
Function: Reformat partitions, partition information depends on $partitions
Example: fastboot oem format
-
fastboot oem at-get-vboot-unlock-challenge
Function: authenticated unlock, needs to obtain unlock challenge data
Example: See 16. fastboot oem at-unlock-vboot
-
fastboot oem at-reset-rollback-index
Function: Reset device rollback data
Example: fastboot oem at-reset-rollback-index
-
fastboot oem at-disable-unlock-vboot
Function: Disable the fastboot oem at-unlock-vboot command
Example: fastboot oem at-disable-unlock-vboot
SD and USB Drive
This chapter mainly introduces SD and USB drive firmware boot and upgrade on the RK platform.
Mechanism Principle
After the boot card and upgrade card are created, a fixed tag is written at a fixed storage offset position in the firmware header, used to mark whether the card is a boot card or an upgrade card. After U-Boot recognizes this tag, it will proceed with the boot or upgrade flow. Among them:
- Boot card: Contains only one complete firmware. U-Boot directly uses this complete firmware to boot the system normally.
- Upgrade card: Contains two sets of firmware. When creating the upgrade card, the PC tool burns two sets of firmware: one containing only the partition images necessary to enter recovery mode (marked as A firmware) and one complete update.img firmware (marked as B firmware). U-Boot uses A firmware to boot the system into recovery mode, and then the recovery program uses B firmware to complete the upgrade.
Special Notes:
- SD card boot/upgrade is supported from the bootrom level.
- USB drive boot/upgrade is only supported from U-Boot level, i.e., users must at least ensure U-Boot works normally.
Firmware Creation
The creation process for SD and USB boot cards and upgrade cards on the RK platform is identical, requiring only two steps:
- Use the
RKTools/linux/Linux_Pack_Firmware/rockdev/tool in the SDK directory to generate update.img. - Use the SDDiskTool tool to burn update.img to SD or USB drive. As shown:
- Select removable disk
- Select "Firmware Upgrade" or "SD Boot"
- Click "Start Creating"

SD Configuration
SD boot/upgrade: The U-Boot released in SDK for each platform already enables this function by default; users do not need additional configuration.
USB Configuration
USB drive boot/upgrade: The U-Boot released in SDK for each platform does not enable this by default. Because U-Boot's native USB scanning command is time-consuming, users should enable it as needed:
-
Step 1: Burn a complete firmware for upgrade to local storage (eMMC/Nand/... etc.) and confirm that this firmware is normal and usable.
-
Step 2: Insert the USB drive and boot into U-Boot command line mode. Execute
usb startandusb infocommands to confirm that the USB drive can be recognized normally; otherwise, debug USB drive recognition first. -
Step 3: Copy a kernel DTB that satisfies step 1, name it kern.dtb, and place it in U-Boot's
./dts/directory. This kern.dtb will be automatically packaged into uboot.img when compiling U-Boot.Purpose of kern.dtb: When the kernel dtb in the local storage partition is damaged, U-Boot uses kern.dtb to ensure USB can be properly initialized.
-
Step 4: Enable USB boot/upgrade configuration in U-Boot
CONFIG_ROCKCHIP_USB_BOOT=yRecompile and flash uboot.img.
If the process indicates that uboot firmware is too large to package, it is caused by adding kern.dtb in step 3. Please remove some unused U-Boot configurations first.
Function Validation
How to confirm whether the SD or USB boot/upgrade function is working.
Users can erase key partitions (kernel, resource, boot, recovery, etc.) on local storage (eMMC, Nand...) and confirm that the kernel can be entered after inserting the SD/USB drive.
Precautions
-
USB drive initialization will call the
usb startcommand, which is relatively time-consuming. -
If the boot/upgrade card needs to support GPT partition table, the SDDiskTool version must be >= v1.59.
-
If the boot/upgrade card needs to support AB system, the SDDiskTool version must be >= v1.61.
-
Since USB drive boot/upgrade was added in 2019.11, the relevant repositories must meet the following conditions:
- U-Boot repository must be updated to the following commit (recommended):
commit 369e944c844f783508b7839ae86a3418e2f63bc7Author: Joseph Chen <chenjh@rock-chips.com>Date: Thu Dec 12 18:07:07 2019 +0800fdt/Makefile: make u-boot-dtb.bin 8-byte alignedThe dts/kern.dtb is appended after u-boot-dtb.bin for U-disk boot.Make sure u-boot-dtb.bin is 8-byte aligned to avoid data-abort oncalling: fdt_check_header(gd->fdt_blob_kern).Signed-off-by: Joseph Chen <chenjh@rock-chips.com>Change-Id: Id5f2daf0c5446e7ea828cb970d3d4879e3acda86Or individually add the following patches (which may be more difficult):
369e944 fdt/Makefile: make u-boot-dtb.bin 8-byte alignedb3b57ac rockchip: board: fix always entering recovery on normal boot U-diske0cee41 rockchip: resource: add sha1/256 verify for kernel dtb5e817a0 tools: rockchip: resource_tool: add sha1 for file entryfc474da lib: sha256: add sha256_csum()0ed06f1 rockchip: support boot from U-disk01f0422 common: bootm: skip usb_stop() if usb is boot device5704c89 fdtdec: support pack "kern.dtb" to the end of u-boot.bin3bdef7e gpt: return 1 directly when test the mbr sector- The rkbin repository must include this commit:
commit f9c0b0b72673a65865b00a8824908ca6f12ecc32Author: Joseph Chen <chenjh@rock-chips.com>Date: Thu Nov 7 09:21:36 2019 +0800tools: resource: add sha1 for file entryBase on U-Boot next-dev branch:(5e817a0 tools: rockchip: resource_tool: add sha1 for file entry)Change-Id: Ife061cabacab488dbecf2a3245d58cc660091dbdSigned-off-by: Joseph Chen <chenjh@rock-chips.com>- The kernel repository must include this commit:
commit 078785057478c789bb033ba06925fa3a07e3130aAuthor: Tao Huang <huangtao@rock-chips.com>Date: Thu Nov 7 17:53:38 2019 +0800rk: scripts/resource_tool: add sha1 for file entryFrom u-boot 5e817a0ea427 ("tools: rockchip: resource_tool: add sha1 for file entry").Merge all C files to one resource_tool.cChange-Id: If63ba77d1f5a3660bd6ef87769bb456fa086ae71Signed-off-by: Tao Huang <huangtao@rock-chips.com> -
If the user's SDK is relatively old, in addition to individually adding the above patches, it is recommended to confirm with the recovery engineer whether the recovery has related patches.