跳到主要内容

Linux A/B System

:::info 文档信息

文档标识:RK-KF-YF-156 · 发布版本:V1.1.0 · 发布日期:2021-03-02 · 页数:17 · 语言:英文

原始文档:Rockchip_Developer_Guide_Linux_AB_System_CN.pdf

:::

章节大纲​

  • Linux A/B System(P1)
    • 引用参考(P4)
    • 术语(P4)
    • 简介(P4)
    • AB 数据格式及存储(P4)
    • 启用配置(P7)
      • pre-loader 说明(P7)
      • uboot 配置(P7)
      • system bootctrl 参考(P7)
        • successful_boot 模式(P7)
        • reset retry 模式(P8)
        • 两种模式的优缺点(P9)
    • 流程(P9)
    • 升级及升级异常处理参考(P16)
      • 从系统升级(P16)
      • 从 recovery 升级(P16)
    • 分区参考(P16)
    • 测试(P17)
      • 测试successful_boot 模式(P17)
      • 测试reset retry 模式(P17)

在线预览​

若预览无法显示,请直接下载 PDF 后用本地阅读器打开。


1. 引用参考​

《Rockchip-Secure-Boot2.0.md》

《Rockchip-Secure-Boot-Application-Note.md》

《Android Verified Boot 2.0》

2. 术语​

3. 简介​

所谓的 A/B System 即把系统固件分为两份,系统可以从其中的一个 slot 上启动。当一份启动失败后可以从另一份启动,同时升级时可以直接将固件拷贝到另一个 slot 上而无需进入系统升级模式。

4. AB 数据格式及存储​

存储位置为 misc 分区偏移 2KB 位置。

/* Magic for the A/B struct when serialized. */
#define AVB_AB_MAGIC "\0AB0"
#define AVB_AB_MAGIC_LEN 4
/* Versioning for the on-disk A/B metadata - keep in sync with avbtool. */
#define AVB_AB_MAJOR_VERSION 1
#define AVB_AB_MINOR_VERSION 0
/* Size of AvbABData struct. */
#define AVB_AB_DATA_SIZE 32
/* Maximum values for slot data */
#define AVB_AB_MAX_PRIORITY 15
#define AVB_AB_MAX_TRIES_REMAINING 7
typedef struct AvbABSlotData {
/* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
* both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
* being the highest. The special value 0 is used to indicate the
* slot is unbootable.
*/
uint8_t priority;
/* Number of times left attempting to boot this slot ranging from 0
* to AVB_AB_MAX_TRIES_REMAINING.
*/
uint8_t tries_remaining;
/* Non-zero if this slot has booted successfully, 0 otherwise. */
uint8_t successful_boot;
/* Reserved for future use. */
uint8_t reserved[1];
} AVB_ATTR_PACKED AvbABSlotData;
/* Struct used for recording A/B metadata.
*
* When serialized, data is stored in network byte-order.
*/
typedef struct AvbABData {
/* Magic number used for identification - see AVB_AB_MAGIC. */
uint8_t magic[AVB_AB_MAGIC_LEN];
/* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
uint8_t version_major;
uint8_t version_minor;
/* Padding to ensure |slots| field start eight bytes in. */
uint8_t reserved1[2];
/* Per-slot metadata. */
AvbABSlotData slots[2];
/* Reserved for future use. */
uint8_t reserved2[12];
/* CRC32 of all 28 bytes preceding this field. */
uint32_t crc32;
} AVB_ATTR_PACKED AvbABData;

对于小容量存储,没有 misc 分区,有 vendor 分区,可以考虑存储到 vendor。

在此基础上增加 lastboot,标记最后一个可启动固件。主要应用于低电情况或工厂生产测试时 retry 次数用完,而还没有进入系统调用 boot_ctrl 服务。

参考如下:

typedef struct AvbABData {
/* Magic number used for identification - see AVB_AB_MAGIC. */
uint8_t magic[AVB_AB_MAGIC_LEN];
/* Version of on-disk struct - see AVB_AB_{MAJOR,MINOR}_VERSION. */
uint8_t version_major;
uint8_t version_minor;
/* Padding to ensure |slots| field start eight bytes in. */
uint8_t reserved1[2];
/* Per-slot metadata. */
AvbABSlotData slots[2];
/* mark last boot slot */
uint8_t last_boot;
/* Reserved for future use. */
uint8_t reserved2[11];
/* CRC32 of all 28 bytes preceding this field. */
uint32_t crc32;
} AVB_ATTR_PACKED AvbABData;

同时在 AvbABSlotData 中增加 is_update 标志位,标志系统升级的状态,更改如下:

typedef struct AvbABSlotData {
/* Slot priority. Valid values range from 0 to AVB_AB_MAX_PRIORITY,
* both inclusive with 1 being the lowest and AVB_AB_MAX_PRIORITY
* being the highest. The special value 0 is used to indicate the
* slot is unbootable.
*/
uint8_t priority;
/* Number of times left attempting to boot this slot ranging from 0
* to AVB_AB_MAX_TRIES_REMAINING.
*/
uint8_t tries_remaining;
/* Non-zero if this slot has booted successfully, 0 otherwise. */
uint8_t successful_boot;
/* Mark update state, mark 1 if the slot is in update state, 0 otherwise. */
uint8_t is_update : 1;
/* Reserved for future use. */
uint8_t reserved : 7;
} AVB_ATTR_PACKED AvbABSlotData;

最后表格来说明各个参数的含义:

AvbABData:

参数含义
priority标志 slot 优先级,0 为不可启动,15 为最高优先级
tries remaining _尝试启动次数,设置为 7 次
successful boot _系统启动成功后会配置该参数,1:该 slot 成功启动,0:该 slot 未成功启动
is update _标记该 slot 的升级状态,1:该 slot 正在升级,0:该 slot 未升级或升级成功

AvbABSlotData:

参数含义
magic结构体头部信息:\0AB0
version major _主版本信息
version minor _次版本信息
slotsslot 引导信息,参见 AvbABData
last boot _上一次成功启动的 slot,0:slot A 上次成功启动,1:slot B 上次成功启动
crc32数据校验

5. 启用配置​

5.1 pre-loader 说明​

目前 pre-loader 支持 A/B slot 分区和单 slot 分区。

5.2 uboot 配置​

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
CONFIG_ANDROID_AB=y

5.3 system bootctrl 参考​

目前 system bootctrl 设计两套控制逻辑,bootloader 全支持这两种逻辑启动。

5.3.1 successful_boot 模式​

正常进入系统后,boot_ctrl 依据 androidboot.slot_suffix,设置当前 slot 的变量:

successful_boot = 1;
priority = 15;
tries_remaining = 0;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

升级系统中,boot_ctrl 设置:升级的slot设置:

successful_boot = 0;
priority = 14;
tries_remaining = 7;
is_update = 1;
lastboot = 0 or 1; :refer to androidboot.slot_suffix

当前slot设置:

successful_boot = 1;
priority = 15;
tries_remaining = 0;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

升级系统完成,boot_ctrl 设置:

升级的slot设置:

successful_boot = 0;
priority = 15;
tries_remaining = 7;
is_update = 0;
lastboot = 0 or 1; :refer to androidboot.slot_suffix

当前slot设置:

successful_boot = 1;
priority = 14;
tries_remaining = 0;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

5.3.2 reset retry 模式​

正常进入系统后,boot_ctrl 依据 androidboot.slot_suffix,设置当前 slot 的变量:

successful_boot = 0;
priority = 15;
tries_remaining = 7;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

升级系统中,boot_ctrl 设置:升级的slot设置:

successful_boot = 0;
priority = 14;
tries_remaining = 7;
is_update = 1;
lastboot = 0 or 1; :refer to androidboot.slot_suffix

当前slot设置:

successful_boot = 0;
priority = 15;
tries_remaining = 7;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

升级系统完成,boot_ctrl 设置:

升级的slot设置:

successful_boot = 0;
priority = 15;
tries_remaining = 7;
is_update = 0;
lastboot = 0 or 1; :refer to androidboot.slot_suffix

当前slot设置:

successful_boot = 0;
priority = 14;
tries_remaining = 7;
is_update = 0;
last_boot = 0 or 1; :refer to androidboot.slot_suffix

5.3.3 两种模式的优缺点​

  1. successful_boot 模式

优点:只要正常启动系统,不会回退到旧版本固件,除非 system bootctrl 配置

缺点:设备长时间工作后,如果存储某些颗粒异常,会导致系统一直重启

  1. reset retry 模式

优点:始终保持 retry 机制,可以应对存储异常问题

缺点:会回退到旧版本固件

6. 流程​

启动流程:AB successful_boot 模式数据流程:AB reset retry 模式数据流程:

7. 升级及升级异常处理参考​

7.1 从系统升级​

参考《Rockchip Linux 升级方案开发指南》。

7.2 从 recovery 升级​

AB system 不考虑支持 recovery 升级。

8. 分区参考​

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@0x0000c
000(misc),0x00001000@0x0000d000(vbmeta_a),0x00001000@0x0000e000(vbmeta_b),0x00020
000@0x0000e000(boot_a),0x00020000@0x0002e000(boot_b),0x00100000@0x0004e000(system
_a),0x00300000@0x0032e000(system_b),0x00100000@0x0062e000(vendor_a),0x00100000@0x
0072e000(vendor_b),0x00002000@0x0082e000(oem_a),0x00002000@0x00830000(oem_b),0x00
10000@0x00832000(factory),0x00008000@0x842000(factory_bootloader),0x00080000@0x00
8ca000(oem),-@0x0094a000(userdata)

9. 测试​

准备一套可测试 AB 的固件。

9.1 测试successful_boot 模式​

  1. 只烧写 slot A,系统从 slot A 启动。设置从 slot B 启动,系统从 slot A 启动。测试完成,清空 misc分区2. 烧写 slot A 与 slot B,启动系统,当前系统为 slot A。设置系统从 slot B 启动,reboot 系统,当前系统为 slot B。测试完成,清空 misc 分区3. 烧写 slot A 与 slot B,迅速 reset 系统 14 次后,retry counter 用完,还能从 last_boot 指定的系统启动,即能正常从 slot A 启动。测试完成,清空 misc 分区4. 烧写 slot A 与 slot B,启动系统,当前系统为 slot A。设置系统从 slot B 启动,reboot 系统,当前系统为 slot B。设置系统从 slot A 启动,reboot 系统,当前系统为 slot A。测试完成,清空 misc 分区

9.2 测试reset retry 模式​

  1. 只烧写 slot A,系统从 slot A 启动。设置从 slot B 启动,系统从 slot A 启动。测试完成,清空 misc分区2. 烧写 slot A 与 slot B,启动系统,当前系统为 slot A。设置系统从 slot B 启动,reboot 系统,当前系统为 slot B。测试完成,清空 misc 分区3. 烧写 slot A 与 slot B,迅速 reset 系统 14 次后,retry counter 用完,还能从 last_boot 指定的系统启动,即能正常从 slot A 启动。测试完成,清空 misc 分区4. 烧写 slot A 与 slot B,其中 slot B 的 boot.img 损坏,启动系统,当前系统为 slot A。设置系统从 slot B 启动,reboot 系统,系统会重启 7 次后,从 slot A 正常启动系统。测试完成,清空 misc 分区5. 烧写 slot A 与 slot B,启动系统,当前系统为 slot A。设置系统从 slot B 启动,reboot 系统,当前系统为 slot B。设置系统从 slot A 启动,reboot 系统,当前系统为 slot A。测试完成,清空 misc 分区