Skip to main content

[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:

ParameterFunction
bootonce-bootloaderBoot into U-Boot fastboot
boot-recoveryBoot into recovery
boot-fastbootBoot 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":

ParameterFunction
update_packageOTA upgrade
retry_countNumber of recovery upgrade attempts, e.g., if power is lost unexpectedly during upgrade, re-enter recovery based on this value
wipe_dataerase user data (and cache), then reboot
wipe_cachewipe cache (but not user data), then reboot
show_textshow the recovery text menu, used by some bootloader
sideload
sideload_auto_rebootan option only available in user-debug build, reboot the device without waiting
just_exitdo nothing, exit and reboot
localesave the locale to cache, then recovery will load locale from cache when reboot
shutdown_afterreturn shutdown
wipe_allErase the entire userdata partition
wipe_abwipe the current A/B device, with a secure wipe of all the partitions in RECOVERY_WIPE
wipe_package_sizewipe package size
prompt_and_wipe_dataprompt the user that data is corrupt, with their consent erase user data (and cache), then reboot
fw_updateSD card firmware upgrade
factory_modeFactory mode, mainly used for device testing, such as PCBA testing
pcba_testEnter PCBA testing
resize_partitionRepartition size, supported by Android Q dynamic partitions
rk_fwupdateSpecify 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:

UBoot_nextdev_DTO

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:

  1. Example command for compiling the main .dts:
dtc -@ -O dtb -o my_main_dt.dtb my_main_dt.dts
  1. Example command for compiling the overlay DT .dts:
dtc -@ -O dtb -o my_overlay_dt.dtbo my_overlay_dt.dts

DTO Enable​

  1. Configuration enable:
CONFIG_CMD_DTIMG=y
CONFIG_OF_LIBFDT_OVERLAY=y
  1. 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​

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

  1. 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
  1. After successful DTO execution, users can use the fdt command 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=ttyFIQ0
    androidboot.baseband=N/A androidboot.veritymode=enforcing
    androidboot.hardware=rk30board androidboot.console=ttyFIQ0
    init=/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:

    1. green: If in LOCKED state and the key used for verification was not set by the end user.
    2. yellow: If in LOCKED state and the key used for verification was set by the end user.
    3. 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:

    1. enforcing: Enforcing mode, represents SELinux is running and has correctly started restricting domain/type.
    2. 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.
    3. disabled: Disabled, SELinux is not actually running.
  • androidboot.mode: Android boot mode, includes normal and charger.

    1. normal: Normal boot.
    2. 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
......
// 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:

RK3326_PX30_HW_ID1

The matching MIPI screen board has another pulldown resistor reserved:

RK3326_PX30_HW_ID2

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​

ChipAndroid SupportLinux Support
rk3128xNY
rk3126NY
rk322xYY
rk3288NY
rk3368NY
rk3328NY
rk3399NY
rk3308NY
px30YY
rk3326YY

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-baseband
    product /* 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-charge
    battery-voltage
    variant
    battery-soc-ok
    slot-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-dh
    at-attest-uuid
    at-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-boot-tool

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 start and usb info commands 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=y

    Recompile 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 start command, 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:

    1. U-Boot repository must be updated to the following commit (recommended):
    commit 369e944c844f783508b7839ae86a3418e2f63bc7
    Author: Joseph Chen <chenjh@rock-chips.com>
    Date: Thu Dec 12 18:07:07 2019 +0800

    fdt/Makefile: make u-boot-dtb.bin 8-byte aligned

    The 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 on
    calling: fdt_check_header(gd->fdt_blob_kern).

    Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
    Change-Id: Id5f2daf0c5446e7ea828cb970d3d4879e3acda86

    Or individually add the following patches (which may be more difficult):

    369e944 fdt/Makefile: make u-boot-dtb.bin 8-byte aligned
    b3b57ac rockchip: board: fix always entering recovery on normal boot U-disk
    e0cee41 rockchip: resource: add sha1/256 verify for kernel dtb
    5e817a0 tools: rockchip: resource_tool: add sha1 for file entry
    fc474da lib: sha256: add sha256_csum()
    0ed06f1 rockchip: support boot from U-disk
    01f0422 common: bootm: skip usb_stop() if usb is boot device
    5704c89 fdtdec: support pack "kern.dtb" to the end of u-boot.bin
    3bdef7e gpt: return 1 directly when test the mbr sector
    1. The rkbin repository must include this commit:
    commit f9c0b0b72673a65865b00a8824908ca6f12ecc32
    Author: Joseph Chen <chenjh@rock-chips.com>
    Date: Thu Nov 7 09:21:36 2019 +0800

    tools: resource: add sha1 for file entry

    Base on U-Boot next-dev branch:
    (5e817a0 tools: rockchip: resource_tool: add sha1 for file entry)

    Change-Id: Ife061cabacab488dbecf2a3245d58cc660091dbd
    Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
    1. The kernel repository must include this commit:
    commit 078785057478c789bb033ba06925fa3a07e3130a
    Author: Tao Huang <huangtao@rock-chips.com>
    Date: Thu Nov 7 17:53:38 2019 +0800

    rk: scripts/resource_tool: add sha1 for file entry

    From u-boot 5e817a0ea427 ("tools: rockchip: resource_tool: add sha1 for file entry").
    Merge all C files to one resource_tool.c

    Change-Id: If63ba77d1f5a3660bd6ef87769bb456fa086ae71
    Signed-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.