当前位置: 首页 > news >正文

RK3566 Buildroot OTA:U-Boot A/B Slot 源码验证记录

cd /work/linuxecho "===== android_ab.c key words ====="
grep -RIn "slot\|suffix\|misc\|priority\|tries\|successful\|magic\|AB0" \
u-boot/common/android_ab.cecho "===== bootargs slot suffix ====="
grep -RIn "android_slotsufix\|androidboot.slot_suffix\|slot_suffix\|slotsufix" \
u-boot/common u-boot/cmd u-boot/arch/arm/mach-rockchip u-boot/include \
2>/dev/nullecho "===== partition slot logic ====="
grep -RIn "system_a\|system_b\|slot_suffix\|part_get_info\|android_part_get_info" \
u-boot/disk u-boot/common u-boot/cmd u-boot/arch/arm/mach-rockchip \
2>/dev/nullecho "===== important code ranges ====="
nl -ba u-boot/disk/part.c | sed -n '680,740p'
nl -ba u-boot/include/configs/evb_rk3568.h | sed -n '1,100p'
nl -ba u-boot/common/android_bootloader.c | sed -n '930,990p'

1. 本文目的

本文用于记录在 Rockchip RK3566 SDK 中,如何通过查找 U-Boot 源码,验证当前系统为什么要使用 system_a / system_b 作为双 RootFS 分区名,以及 U-Boot 是如何利用 Android A/B slot 机制选择当前启动槽位的。

本文基于当前源码检索结果整理,主要涉及以下文件:

u-boot/common/android_ab.c
u-boot/common/android_bootloader.c
u-boot/disk/part.c
u-boot/common/spl/spl_ab.c
u-boot/common/spl/spl_fit.c
u-boot/cmd/bootfit.c
u-boot/cmd/boot_android.c
u-boot/include/android_ab.h
u-boot/include/android_bootloader_message.h
u-boot/include/android_avb/rk_avb_ops_user.h
u-boot/include/android_image.h

核心结论如下:

当前 RK3566 U-Boot 已启用 Android A/B slot 相关逻辑。U-Boot 启动时会获取当前 slot 后缀 _a_b,并在分区查找阶段将基础分区名追加当前 slot 后缀,从而查找类似 system_a / system_b 这样的分区。因此,Buildroot 双 RootFS 分区命名为 system_a / system_b,是为了复用 Rockchip U-Boot 已经实现的 Android A/B 分区选择机制。


2. 验证入口:U-Boot 中确实存在 A/B slot 逻辑

本次源码检索首先针对 U-Boot 中的 A/B 相关关键字进行搜索:

cd /work/linuxgrep -RIn "slot\|suffix\|misc\|priority\|tries\|successful\|magic\|AB0" \
u-boot/common/android_ab.c

搜索结果显示,u-boot/common/android_ab.c 中存在大量 A/B slot metadata 相关字段,例如:

priority
tries_remaining
successful_boot
slot_suffix
magic
misc

其中比较关键的结果包括:

37:     const struct android_slot_metadata metadata = {
38:             .priority = 15,
39:             .tries_remaining = 7,
40:             .successful_boot = 0,
44:     memcpy(abc->slot_suffix, "a\0\0\0", 4);
45:     abc->magic = ANDROID_BOOT_CTRL_MAGIC;
47:     abc->nb_slot = ARRAY_SIZE(abc->slot_info);

这说明 U-Boot 中维护了 A/B slot 的 metadata。每个 slot 会有:

字段 含义
priority slot 优先级,优先级越高越优先启动
tries_remaining 剩余启动尝试次数
successful_boot 该 slot 是否已经成功启动过
verity_corrupted slot 是否损坏或校验失败
slot_suffix 当前选择的 slot 标识
magic A/B metadata 魔数,用于判断 metadata 是否有效

这与 Android A/B OTA 的基本机制一致:新系统写入 inactive slot 后,bootloader 会尝试启动新 slot;如果新系统未被确认成功启动,启动尝试次数会逐步减少;如果次数耗尽,则该 slot 会被认为不可启动,从而回退到另一个 slot。


3. A/B metadata 的默认值与 slot 状态

android_ab.c 中可以看到默认 slot metadata:

37:     const struct android_slot_metadata metadata = {
38:             .priority = 15,
39:             .tries_remaining = 7,
40:             .successful_boot = 0,

这说明默认情况下,slot 具备较高优先级和一定次数的启动尝试机会,但 successful_boot 初始为 0。

可以这样理解:

priority = 15表示该 slot 具有较高启动优先级。tries_remaining = 7表示该 slot 还允许尝试启动 7 次。successful_boot = 0表示该 slot 尚未被系统确认启动成功。

这对于 OTA 很重要。正常 OTA 流程中,新系统写入 inactive slot 后,bootloader 会尝试启动新 slot。如果系统成功启动,用户态需要调用类似 mark-successful 的动作,将该 slot 标记为成功。如果没有标记成功,bootloader 会继续减少 tries_remaining,最终可能回滚。


4. U-Boot 如何选择当前 slot

检索结果中有一组关键逻辑:

138:static int android_ab_compare_slots(const struct android_slot_metadata *a,
139:                                const struct android_slot_metadata *b)
141:    /* Higher priority is better */
142:    if (a->priority != b->priority)
143:            return b->priority - a->priority;
145:    /* Higher successful_boot value is better, in case of same priority. */
146:    if (a->successful_boot != b->successful_boot)
147:            return b->successful_boot - a->successful_boot;
149:    /* Higher tries_remaining is better to ensure round-robin. */
150:    if (a->tries_remaining != b->tries_remaining)
151:            return b->tries_remaining - a->tries_remaining;

这说明 U-Boot 选择 slot 时主要比较三个指标:

  1. priority
  2. successful_boot
  3. tries_remaining

选择规则可以概括为:

优先选择 priority 更高的 slot;
如果 priority 相同,优先选择 successful_boot 为真的 slot;
如果 successful_boot 也相同,优先选择 tries_remaining 更多的 slot。

对应代码注释也能说明:

198:     * We select a with the higher priority slot that
200:     *  - either has tries_remaining > 0 or successful_boot is true.
201:     * If the slot selected has a false successful_boot, we also decrement
202:     * the tries_remaining until it eventually becomes unbootable because
203:     * tries_remaining reaches 0.

也就是说,U-Boot 会选择一个可启动 slot。如果该 slot 还没有被标记为成功启动,则会减少其剩余尝试次数:

239:    if (slot >= 0 && !abc->slot_info[slot].successful_boot) {
240:            printf("ANDROID: Attempting slot %c, tries remaining %d\n",
241:                   ANDROID_BOOT_SLOT_NAME(slot),
242:                   abc->slot_info[slot].tries_remaining);
243:            abc->slot_info[slot].tries_remaining--;

这正是 A/B OTA 支持失败回滚的基础。


5. U-Boot 从哪里读取 A/B 信息:misc 分区

检索结果多次出现 misc 分区:

63: * @part_info: partition in 'dev_desc' where to read from, normally the "misc"
273:int read_misc_virtual_ab_message(struct misc_virtual_ab_message *message)
293:            debug("%s: Could not found misc partition\n",
307:int write_misc_virtual_ab_message(struct misc_virtual_ab_message *message)
327:            debug("%s: Could not found misc partition\n",

同时在 android_ab.c 中还有:

291: ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);
325: ret = part_get_info_by_name(dev_desc, PART_MISC, &part_info);

这说明 U-Boot 会通过分区名 misc 找到 misc 分区,并从中读取或写入 A/B 相关 metadata。

因此,在前面进行分区改造时保留 misc 分区是必要的。它不是 RootFS,也不是用户数据分区,而是 bootloader 用来保存启动状态、slot 信息、启动尝试次数等数据的地方。


6. 当前 slot 后缀的获取:ab_get_slot_suffix()

检索结果显示:

444:int ab_get_slot_suffix(char *slot_suffix)
446:    /* TODO: get from pre-loader or misc partition */
447:    if (rk_avb_get_current_slot(slot_suffix)) {
448:            printf("rk_avb_get_current_slot() failed\n");
452:    if (slot_suffix[0] != '_') {
454:            printf("###There is no bootable slot, bring up lastboot!###\n");
456:                    memcpy(slot_suffix, "_b", 2);
458:                    memcpy(slot_suffix, "_a", 2);

这段非常关键。

它说明 U-Boot 会调用:

rk_avb_get_current_slot(slot_suffix)

来获取当前 slot 后缀。正常情况下,结果应该是:

_a

或:

_b

如果获取到的 slot_suffix 不是以下划线开头,U-Boot 还会执行 fallback 逻辑,尝试回到上一次可用 slot。

这说明当前 slot 后缀不是 Linux 自己决定的,而是在 U-Boot 启动阶段已经被确定。


7. U-Boot 如何把当前 slot 传给 Linux

继续搜索启动参数相关关键字:

grep -RIn "android_slotsufix\|androidboot.slot_suffix\|slot_suffix\|slotsufix" \
u-boot/common u-boot/cmd u-boot/arch/arm/mach-rockchip u-boot/include \
2>/dev/null

结果中最关键的是:

u-boot/common/android_bootloader.c:949: /* Get current slot_suffix */
u-boot/common/android_bootloader.c:950: if (ab_get_slot_suffix(slot_suffix))
u-boot/common/android_bootloader.c:1058:        env_set("android_slotsufix", slot_suffix);
u-boot/common/android_bootloader.c:1075:        command_line = android_assemble_cmdline(slot_suffix, mode_cmdline);

其中:

env_set("android_slotsufix", slot_suffix);

说明 U-Boot 会把当前 slot 后缀写入环境变量 android_slotsufix

这也解释了为什么在 Linux 中执行:

cat /proc/cmdline

可以看到类似:

android_slotsufix=_a

需要注意的是,android_slotsufix 这个名字里 suffix 少了一个 f,看起来像拼写错误,但这是 Rockchip U-Boot 代码中实际使用的字段名。因此在本项目中应以实际板端 /proc/cmdline 中看到的字段为准。


8. android_bootloader.c 中的启动流程

打印 u-boot/common/android_bootloader.c 的 930 到 990 行后,可以看到:

930                  printf("Could not find misc partition\n");
937                  mode = android_bootloader_load_and_clear_mode(dev_desc,
938                                                                &misc_part_info);
947          printf("ANDROID: reboot reason: \"%s\"\n", android_boot_mode_str(mode));
948  #ifdef CONFIG_ANDROID_AB
949          /* Get current slot_suffix */
950          if (ab_get_slot_suffix(slot_suffix))
951                  return -1;
952  #endif

这段说明 U-Boot 启动时会先处理启动模式,例如 normal、recovery、bootloader 等,然后在启用 CONFIG_ANDROID_AB 时获取当前 slot 后缀。

接着:

953          switch (mode) {
954          case ANDROID_BOOT_MODE_NORMAL:
...
982  #ifdef CONFIG_ANDROID_AB
983                  boot_partname = ab_can_find_recovery_part() ?
984                          ANDROID_PARTITION_RECOVERY : ANDROID_PARTITION_BOOT;

这说明 U-Boot 会根据启动模式决定加载 boot 还是 recovery,同时 A/B 情况下有特殊处理。

对于本文关注的 Buildroot A/B RootFS 来说,重点不是 Android 正常启动流程本身,而是:

U-Boot 已经获取 slot_suffix;
U-Boot 会把 slot_suffix 写入启动参数;
后续分区查找逻辑会利用 slot_suffix。

9. 最关键的分区查找逻辑:part_get_info_by_name_option()

本次验证中最重要的代码来自:

u-boot/disk/part.c

打印 680 到 740 行:

nl -ba u-boot/disk/part.c | sed -n '680,740p'

得到关键代码:

682  static int part_get_info_by_name_option(struct blk_desc *dev_desc,
683                                          const char *name,
684                                          disk_partition_t *info,
685                                          bool strict)
686  {
687          struct part_driver *part_drv;
688          char name_slot[32] = {0};
689          int none_slot_try = 1;
690          int ret, i;

这里定义了一个关键变量:

char name_slot[32] = {0};

它用于保存追加了 slot 后缀之后的分区名。


10. 如果调用方已经带 _a/_b,U-Boot 会先去掉后缀

继续看:

702  #if defined(CONFIG_ANDROID_AB) || defined(CONFIG_SPL_AB)
703          char *name_suffix = (char *)name + strlen(name) - 2;
704
705          /* Fix can not find partition with suffix "_a" & "_b". If with them, clear */
706          if (!memcmp(name_suffix, "_a", strlen("_a")) ||
707              !memcmp(name_suffix, "_b", strlen("_b")))
708                  memset(name_suffix, 0, 2);
709  #endif

这段逻辑说明:

如果传入的分区名本身已经带 _a_b 后缀,U-Boot 会先把这个后缀清掉。

例如传入:

system_a

可能会先变成:

system

然后再由当前 slot 统一追加后缀。

这样做的目的通常是避免出现重复后缀,例如:

system_a_a

也就是说,在 A/B 模式下,U-Boot 更倾向于使用“基础分区名 + 当前 slot 后缀”的统一规则,而不是让上层到处手动传 system_asystem_b


11. A/B 模式下,U-Boot 会追加当前 slot 后缀

最关键的代码是:

710  #if defined(CONFIG_ANDROID_AB) && !defined(CONFIG_SPL_BUILD)
711          /* 1. Query partition with A/B slot suffix */
712          if (rk_avb_append_part_slot(name, name_slot))
713                  return -1;

注释已经写得很清楚:

Query partition with A/B slot suffix

也就是:

查询分区时,优先使用带 A/B slot 后缀的分区名。

虽然本次输出还没有展开 rk_avb_append_part_slot() 的函数定义,但从函数名和上下文已经能看出它的目的:

rk_avb_append_part_slot(name, name_slot)

即根据当前 A/B slot,把基础分区名 name 转换成带 slot 后缀的 name_slot

可以理解为:

name = "system"
slot_suffix = "_a"
name_slot = "system_a"

或:

name = "system"
slot_suffix = "_b"
name_slot = "system_b"

12. U-Boot 用追加后缀后的名字查找分区表

后面真正查分区表的是这一段:

720  lookup:
721          debug("## Query partition(%d): %s\n", none_slot_try, name_slot);
722          for (i = 1; i < part_drv->max_entries; i++) {
723                  ret = part_drv->get_info(dev_desc, i, info);
724                  if (ret != 0) {
725                          /* no more entries in table */
726                          break;
727                  }
728                  if (strcmp(name_slot, (const char *)info->name) == 0) {
729                          /* matched */
730                          return i;
731                  }
732          }

这说明 U-Boot 最终会拿 name_slot 与分区表中的分区名进行比较:

strcmp(name_slot, info->name)

因此,如果当前 slot 是 _a,并且基础分区名为 system,那么 U-Boot 会查找:

system_a

如果当前 slot 是 _b,则查找:

system_b

这就解释了为什么 parameter-buildroot-fit.txt 中必须定义:

system_a
system_b

而不是随便定义成其他名字。


13. 如果带 slot 后缀的分区找不到,U-Boot 会回退查基础分区名

代码后面还有 fallback 逻辑:

734          /* 2. Query partition without A/B slot suffix if above failed */
735          if (none_slot_try) {
736                  none_slot_try = 0;
737                  strcpy(name_slot, name);
738                  goto lookup;
739          }

这说明 U-Boot 的查找流程是:

第一步:先查带 slot 后缀的分区名,例如 system_a 或 system_b;
第二步:如果查不到,再尝试查原始分区名,例如 system。

这是一种兼容设计。

也就是说,开启 A/B 后,如果分区表中存在 system_a/system_b,就会优先命中带后缀的分区。如果不存在,U-Boot 可能还会尝试查普通 system 分区。

但对于 A/B OTA 来说,应该明确提供 system_a/system_b,这样才能让 slot 选择真正生效。


14. SPL 阶段也存在 A/B 后缀处理

搜索结果中还出现了 SPL 相关逻辑:

u-boot/common/spl/spl_ab.c:258: char slot_suffix[3] = {0};
u-boot/common/spl/spl_ab.c:265: if (spl_get_current_slot(dev_desc, "misc", slot_suffix)) {
u-boot/common/spl/spl_ab.c:272: strcat(new_name, slot_suffix);
u-boot/common/spl/spl_ab.c:292: char slot_suffix[3] = {0};
u-boot/common/spl/spl_ab.c:295: ret = spl_get_current_slot(dev_desc, "misc", slot_suffix);
u-boot/common/spl/spl_ab.c:299: if (!strncmp(slot_suffix, "_a", 2))
u-boot/common/spl/spl_ab.c:301: else if (!strncmp(slot_suffix, "_b", 2))

这里更加直接地出现了:

strcat(new_name, slot_suffix);

这说明在 SPL 阶段,也存在将分区基础名和 slot 后缀拼接的逻辑。

虽然我们当前 Buildroot RootFS 的主要验证点是在 U-Boot 阶段,但 SPL 代码进一步说明 Rockchip 的启动链路中确实使用 _a/_b 作为 A/B slot 命名规则。


15. FIT 启动参数中也会追加 A/B 信息

搜索结果中还有:

u-boot/common/spl/spl_fit.c:541:                        char slot_suffix[3] = {0};
u-boot/common/spl/spl_fit.c:543:                        if (!spl_get_current_slot(info->dev, "misc", slot_suffix))
u-boot/common/spl/spl_fit.c:544:                                fdt_bootargs_append_ab((void *)image_info.load_addr, slot_suffix);

这说明在 SPL FIT 镜像加载过程中,也会获取当前 slot 后缀,并通过:

fdt_bootargs_append_ab(...)

把 A/B 信息追加到设备树或启动参数中。

这与我们在 Linux 中看到的:

android_slotsufix=_a

属于同一类现象,即 bootloader 在启动 Linux 之前,已经把当前 A/B slot 信息写入了启动参数。


16. bootfit.c 中也会追加 android_slotsufix

搜索结果中还有:

u-boot/cmd/bootfit.c:98:        char slot_suffix[3] = {0};
u-boot/cmd/bootfit.c:99:        char slot_info[21] = "android_slotsufix=";
u-boot/cmd/bootfit.c:101:       if (ab_get_slot_suffix(slot_suffix))
u-boot/cmd/bootfit.c:104:       strcat(slot_info, slot_suffix);

这说明在 bootfit 启动命令中,也会拼接:

android_slotsufix=_a

或:

android_slotsufix=_b

也就是说,不止 android_bootloader.c,Rockchip 的 FIT 启动路径中也有 A/B slot 信息传递逻辑。


17. boot_android.c 中明确存在 _a/_b 后缀数组

搜索结果还显示:

u-boot/cmd/boot_android.c:547:  const char * slot_suffixes[2] = {"_a", "_b"};
u-boot/cmd/boot_android.c:563:                          slot_suffixes[n],

这说明 U-Boot 的 Android 启动命令中明确将 _a_b 作为两个 slot 后缀。

这与我们在分区命名中使用:

system_a
system_b

保持一致。


18. 为什么源码中没有大量写死 system_a/system_b

在源码搜索中,直接搜索 system_asystem_b 并没有出现很多结果,这是正常的。

原因是 U-Boot 的 A/B 机制通常不会到处写死:

"system_a"
"system_b"

而是采用通用规则:

基础分区名 + 当前 slot 后缀

例如:

system + _a = system_a
system + _b = system_b
boot + _a = boot_a
boot + _b = boot_b
vendor + _a = vendor_a
vendor + _b = vendor_b

这种机制更通用,适配 Android A/B 体系中多个 slot 化分区。

因此,在源码中更常见的是:

slot_suffix
_a
_b
append_part_slot
part_get_info_by_name

而不是直接写死 system_a/system_b


19. 为什么 Buildroot 也要命名成 system_a/system_b

虽然当前系统运行的是 Buildroot,而不是完整 Android,但我们复用了 Rockchip U-Boot 的 Android A/B 启动机制。

U-Boot 的分区查找逻辑是:

基础分区名 + 当前 slot suffix

如果基础分区名是 system,当前 slot 是 _a,则实际查找:

system_a

如果当前 slot 是 _b,则实际查找:

system_b

因此,Buildroot 的 RootFS 分区命名为:

system_a
system_b

本质上是为了适配 U-Boot 已有的 A/B slot 选择逻辑。

如果随便命名成:

rootfs_a
rootfs_b

那么除非同步修改 U-Boot 中查找的基础分区名为 rootfs,否则默认逻辑下可能不会正确查到这些分区。

所以本项目的设计不是重新发明一套 OTA slot 机制,而是让 Buildroot RootFS 适配 Rockchip U-Boot 已有的 Android A/B 规则。


20. 与 parameter-buildroot-fit.txt 的关系

前面已经确认,parameter-buildroot-fit.txt 中定义了:

0x00600000@0x00058000(system_a)
0x00600000@0x00658000(system_b)

以及:

uuid:system_a=614e0000-0000-4b53-8000-1d28000054a9
uuid:system_b=614e0001-0000-4b53-8000-1d28000054a9

这说明板端分区表中实际存在:

system_a
system_b

而 U-Boot 源码中又存在:

基础分区名 + slot suffix

的分区查找逻辑。

因此两者是配合关系:

U-Boot 当前 slot = _a↓
U-Boot 查找 system_a↓
parameter 中存在 system_a↓
成功找到 A 槽 RootFSU-Boot 当前 slot = _b↓
U-Boot 查找 system_b↓
parameter 中存在 system_b↓
成功找到 B 槽 RootFS

21. 与 rk356x-package-file-ab-rootfs 的关系

前面已经确认,rk356x-package-file-ab-rootfs 中包含:

system_a    Image/rootfs.img
system_b    Image/rootfs.img

它的作用不是决定 U-Boot 怎么选择 slot,而是在完整固件打包阶段告诉 Rockchip 打包工具:

把 Image/rootfs.img 写入 system_a;
把 Image/rootfs.img 也写入 system_b。

这样首次完整烧录后,两个 RootFS 分区中都有系统文件。

三者关系可以总结为:

parameter-buildroot-fit.txt定义 system_a / system_b 分区存在。rk356x-package-file-ab-rootfs把 rootfs.img 写入 system_a / system_b。U-Boot A/B slot 逻辑根据当前 slot 选择 system_a 或 system_b 启动。

22. 当前验证链路总结

根据本次源码检索,可以形成如下完整证据链:

1. U-Boot 中存在 CONFIG_ANDROID_AB 相关逻辑↓
2. android_ab.c 中存在 slot metadata↓
3. metadata 包含 priority / tries_remaining / successful_boot↓
4. U-Boot 会根据 priority、successful_boot、tries_remaining 选择可启动 slot↓
5. ab_get_slot_suffix() 会获取当前 slot 后缀 _a 或 _b↓
6. android_bootloader.c 会将 slot_suffix 写入 android_slotsufix↓
7. Linux 启动后 /proc/cmdline 可看到 android_slotsufix=_a 或 _b↓
8. part.c 的 part_get_info_by_name_option() 在 A/B 模式下会调用 rk_avb_append_part_slot()↓
9. U-Boot 查分区时优先使用带 A/B slot 后缀的分区名↓
10. 基础分区名 system 在 _a 槽下对应 system_a,在 _b 槽下对应 system_b↓
11. 因此 Buildroot 双 RootFS 分区命名为 system_a/system_b 是为了适配 Rockchip U-Boot 的 A/B slot 机制

23. 当前还缺的最后一个源码闭环

本次结果已经证明:

part_get_info_by_name_option()调用了 rk_avb_append_part_slot(name, name_slot)

但还没有展开 rk_avb_append_part_slot() 的函数定义。

为了让证据链更完整,建议继续在 VSCode 或命令行中搜索:

cd /work/linuxgrep -RIn "rk_avb_append_part_slot" u-boot 2>/dev/null

找到函数定义后,重点看它是否存在类似逻辑:

strcpy(name_slot, name);
strcat(name_slot, slot_suffix);

或:

snprintf(name_slot, ..., "%s%s", name, slot_suffix);

如果能看到这类代码,就可以完全确认:

system + _a = system_a
system + _b = system_b

不过,即使当前还没有展开这个函数定义,结合 part.c 中的注释:

Query partition with A/B slot suffix

以及 SPL 中已经出现的:

strcat(new_name, slot_suffix)

也已经足以说明 Rockchip U-Boot 使用的是“基础分区名 + A/B slot 后缀”的规则。


24. 推荐补充验证命令

为了进一步完善文档,建议继续执行以下命令:

cd /work/linuxgrep -RIn "rk_avb_append_part_slot" u-boot 2>/dev/null

如果找到定义,例如在某个文件中显示:

u-boot/xxx/yyy.c:123:int rk_avb_append_part_slot(...)

则继续执行:

nl -ba u-boot/xxx/yyy.c | sed -n '110,150p'

还可以继续查 rk_avb_get_current_slot()

grep -RIn "rk_avb_get_current_slot" u-boot 2>/dev/null

重点确认:

当前 slot 后缀来自哪里;
是否读取 misc / avb_ab metadata;
是否会返回 _a 或 _b。

25. 文档中可使用的最终表述

可以将以下内容直接写入项目文档:

通过检索 U-Boot 源码可以确认,当前 RK3566 U-Boot 已启用 Android A/B slot 相关逻辑。`u-boot/common/android_ab.c` 中维护了 A/B slot metadata,包括 priority、tries_remaining、successful_boot、slot_suffix 等字段。U-Boot 会根据这些字段选择当前可启动 slot,并通过 `ab_get_slot_suffix()` 获取当前 slot 后缀 `_a` 或 `_b`。在 `u-boot/common/android_bootloader.c` 中,U-Boot 会调用 `ab_get_slot_suffix(slot_suffix)` 获取当前 slot,并通过 `env_set("android_slotsufix", slot_suffix)` 将 slot 信息写入启动参数。因此 Linux 启动后可以在 `/proc/cmdline` 中看到 `android_slotsufix=_a` 或 `android_slotsufix=_b`。最关键的是,在 `u-boot/disk/part.c` 的 `part_get_info_by_name_option()` 函数中,当启用 `CONFIG_ANDROID_AB` 后,U-Boot 会调用 `rk_avb_append_part_slot(name, name_slot)`,优先使用带 A/B slot 后缀的分区名进行查找。也就是说,如果基础分区名为 `system`,当前 slot 为 `_a`,则实际查找 `system_a`;当前 slot 为 `_b`,则实际查找 `system_b`。因此,Buildroot 双 RootFS 分区命名为 `system_a / system_b` 并不是随意命名,而是为了复用 Rockchip U-Boot 已有的 Android A/B slot 选择机制。

26. 本阶段结论

本阶段源码验证可以得出以下结论:

  1. 当前 U-Boot 源码中存在完整的 Android A/B slot 相关逻辑。
  2. android_ab.c 中维护了 slot metadata,包括优先级、启动尝试次数和启动成功标志。
  3. U-Boot 会从 misc / AVB A/B 信息中获取当前 slot 后缀。
  4. 当前 slot 后缀为 _a_b
  5. U-Boot 会把 slot 后缀写入启动参数,因此 Linux 中可以看到 android_slotsufix=_a/_b
  6. U-Boot 查找分区时会优先查询带 A/B slot 后缀的分区名。
  7. 因此,基础分区名 system 在 A 槽下对应 system_a,在 B 槽下对应 system_b
  8. Buildroot 使用 system_a/system_b 命名,是为了直接复用 Rockchip U-Boot 的 Android A/B slot 机制。
  9. parameter-buildroot-fit.txt 负责定义 system_a/system_b 分区。
  10. rk356x-package-file-ab-rootfs 负责在完整固件烧录时把 rootfs.img 同时写入 system_a/system_b
  11. U-Boot A/B 逻辑负责根据当前 slot 选择对应分区启动。

一句话总结:

system_a / system_b 不是为了看起来像 Android,而是因为 Rockchip U-Boot 的 A/B 分区查找逻辑就是按照“基础分区名 + slot 后缀”的方式工作的。Buildroot 这样命名,是为了让自己的 RootFS 能接入已有的 bootloader A/B 切换机制。

http://www.jsqmd.com/news/958274/

相关文章:

  • 宜宾酒柜定制厂家排行:宜宾全屋各种定制/宜宾全屋定制厂家/宜宾墙板定制/宜宾榻榻米定制/实地实测品质对比推荐 - 优质品牌商家
  • 2026东莞装修沙子实测评测:四大供应商核心维度对比 - 优质品牌商家
  • 抖音批量下载架构深度解析:从API破解到智能策略切换的实战指南
  • 4层板DDR2/DDR3高速PCB设计:信号完整性实战指南
  • 2026年品牌加州鲈鱼苗价格排名 - myqiye
  • Rust周刊2026W21 | Toasty 0.6.0发布、kache 0.3.0发布、image-rs性能提升5倍、Tonic加入gRPC项目、cargo-crap发布
  • DDrawCompat终极指南:三步拯救Windows老游戏兼容性难题
  • 2026年01专业粉末自动包装机厂家推荐榜 - 优质品牌商家
  • 手把手教你用Vivado仿真SelectIO IP核:从testbench到数据对齐实战
  • 如何快速掌握Window Resizer:打破Windows窗口限制的终极指南
  • 2026苏州优质GEO公司盘点,助力品牌企业抢占AI搜索流量 - 招财兔数字员工
  • Waifu2x-Extension-GUI:让模糊影像重获新生的AI超分辨率工具
  • 2026年别墅入户门服务商推荐 - myqiye
  • AI数学导师实战:Streamlit+LangChain构建教学级解题思维链
  • 为 LLM 预留“插座”:设计可插拔的 AI 能力底座
  • Windows 11优化利器:Win11Debloat让你的电脑告别卡顿与隐私泄露
  • 扩展 Lucas 定理学习笔记 详解,一文带你彻底看懂扩展 Lucas 定理。
  • 天津古玩回收,京顺斋上门服务,让古物重焕光彩 - 深鉴新闻
  • 2026年6月上海geo优化公司推荐:五大专业评测应对AI搜索新挑战 - 品牌推荐
  • 2026年电动叉车老牌厂家排名,性价比高的有哪些 - myqiye
  • Chart.js 气泡图
  • 南宁家政红黑榜:2026年这四家进入口碑决赛圈,冠军表现亮眼 - 教育信息速递
  • 微信单向好友检测终极指南:3分钟找出谁删了你,清理虚假社交关系
  • 炉石传说HsMod终极指南:如何免费解锁完整自定义体验
  • 3步解锁Windows安卓应用新体验:轻量级APK安装器完全指南
  • 读后感PPT模板怎么选?主流平台实测体验分享 - 品牌测评鉴赏家
  • 如何实现高性能游戏服务器:ET框架的分布式架构与组件化设计解析
  • Windows 11系统优化神器:Win11Debloat如何让你的电脑快如闪电?
  • 基于实时日志解析与模块化架构的炉石传说智能辅助系统实现
  • python字串切片