Bootloader_AB分区说明

1. 概述

本文旨在介绍SigmaStar平台实现Android AB分区特性的细节。其中包括在SigmaStar Android平台上开启AB分区的配置说明、烧录说明、异常情况的处理、AB分区启动代码流程等。阅读本文前,请至少了解如下内容,下文会简单说明:

  1. SigmaStar的分区配置方法、Fstab配置方法。
  2. 原生Android AB分区的layout及其启动过程AB分区选择的状态机

2. 基础介绍

2.1 SigmaStar的分区配置方法、Fstab配置方法

请参考下列文档:

2.2 原生Android AB分区的layout及其启动过程AB分区选择的状态机

分区layout如下图:

原生流程图如下图:

其中,"Read boot slot metadata"中的metadata指的是管理AB状态机的数据结构,它一般被存放在misc分区起始偏移2KByte的位置。其中包含的信息大致如下图:

3. SigmaStar AB方案介绍

3.1 分区配置

3.1.1 分区布局

在SigmaStar平台AB分区layout大致如下(其中只列了一些关键的分区):

可以看到,在SigmaStar平台的AB分区中,较特殊的分区有:

  • misc分区被固定在UDA分区的LBA1024,即第1(此处与后文提到LBA、block均为0起始)个erase block之后。
  • bootloader_a分区被固定在UDA分区的LBA2048,即第2个erase block。Non-AB设备中,LBA2048也是bootloader分区的起始位置。
  • bootloader_b分区被固定在UDA分区的LBA10240,即bootloader_分区的大小是4Mbyte,bootloader_b紧随bootloader_a。

如此设定的原因是因为SigmaStar的AB分区是包含bootloader分区的,即IPL、IPL_CUST、U-boot也是分AB的。因为这个特性,Android AB状态机选择当前启动是从slot a还是slot b的动作就得由IPL更前面一级的loader来完成。显然ROM code来做AB select不太现实(code size有限),于是引入了IPL_PRE做bootloader的AB启动选择,IPL_PRE只包含了eMMC相关的基本初始化流程并且运行在IMI所以无需频繁更新,IPL_PRE受其所运行在IMI的限制,其code size也不可能太大,所以将IPL_PRE需要读写到的分区都固定在了UDA固定的偏移。

3.1.2 misc分区

在SigmaStar平台的misc分区中同样包含了标准的AB metadata,详见2.2章节。

3.2 大致软件流程

在SigmaStar平台实现的Android AB状态机大致流程图如下:

该流程图体现了2.2章Android给出的启动时AB分区选择的状态机在SigmaStar平台的大致实现,其中值得注意的是:

SigmaStar的AB状态机大致和Google给出的状态机一致。主要的差异在当AB设备启动发现没有可用的slot时,会写一条"bootonce-bootloader"的bootloader message,然后强制从LBA2048(bootloader_a分区)去加载下一阶段镜像,如果最终能够正常启动到U-boot,U-boot走到boota流程读到bootloader message时,会根据"bootonce-bootloader"指示进到fastboot mode。从原生的状态机可以看到,一旦没有可用的slot时,当下就要直接进入fastboot模式;而在SigmaStar这样做的原因是IPL_PRE受codesize以及现有代码框架的限制,很难支持fastboot驱动,所以在SigmaStar平台才有如下变化:当IPL_PRE做AB选择时发现没slot可用,会尝试从slot a去启动到U-boot并进入到fastboot模式来重烧

3.3 烧录说明

本章节列出了一些烧录方法的流程介绍,旨在介绍如何结合SigmaStar AB启动流程正确的为空片、非空片的开发板进行烧录,适配其他烧录方法可以参考本章。

3.3.1 fastboot烧录脚本

fastboot烧录脚本位于:<AOSP>/vendor/sigmastar/tools/sstar_fastboot_flash_tool/sstar_fastboot_flashall.bat 该脚本的核心流程就是执行fastboot flash <partition_name> <image_path>,镜像烧录先后顺序大致如下:

  1. 烧录GPT(fastboot flash gpt partition_table.img),更新板子上的分区表,为后面烧录镜像提供分区位置支持。
  2. 烧录IPL_PRE.bin到BOOT1硬件分区(fastboot flash BOOT1 IPL_PRE.bin),fastboot flash命令流程会对BOOT1或BOOT2这个分区做特殊处理,将传递过来的镜像烧录到eMMC的BOOT1或BOOT2硬件分区
  3. 烧录其他镜像。(fastboot flash <partition_name> <partition_name>.img

对于其他的烧录方式,可能不需要硬性规定镜像烧录顺序,需要注意的是IPL_PRE.bin要烧录到BOOT1和BOOT2硬件分区。

3.3.2 空片烧录示例

下面举例空片烧录如何使用flashtool搭配fastboot脚本完成烧录(非空片下也可以使用此方法):

  1. 空片状态的板子可以看到类似如下log,此时因为是空片,板子当前HALT在ROM:

    E:CD
    HDR ERR 0000e000
    HDR ERR 0000e001
    HDR ERR 0000e002
    
  2. 因为是空片状态,所以要先烧录IPL_PRE.bin到BOOT1和bootloader.img到UDA的LBA2048位置,需要使用大于等于5.0.31版本的Flash Tool才支持往UDA分区烧镜像。烧录前需要将所有的配置选好之后再点“connect”按钮,例如烧录完IPL_PRE.bin到BOOT1之后,接下来要烧bootloader.img到UDA,请先点“disconnect”按钮,之后再勾选所需的设置,最后再重新点“connect”按钮,否则会出现不符合预期的情况。

    先烧录IPL_PRE.bin,设置如下图。

再烧录bootloader.img,设置如下图,和烧IPL_PRE.bin勾选的配置不同之处已经圈出。

  1. 当板子至少有了IPL_PRE.bin和bootloader.img之后,开机会出现类似如下log,可以看到进入了fastboot模式:

    E:CD
    
    IPL_PRE g3385319
    [SDMMC] NO SD!
    Force boot slot a and enter fastboot mode
    CPU=1000Mhz
    
    IPL g3385319
    ......
    Force boot slot a and enter fastboot mode
    Checksum OK
    
    IPL_CUST g3385319
    ......
    Force boot slot a and enter fastboot mode
    
    U-Boot 2021.10 (Jun 05 2023 - 21:37:47 +0800)
    Error: Could not find env partition
    Info: Dtbo list is not set or empty, not thining to do
    Loading Environment from MMC...
    Hit any key to stop autoboot:  0
    <USB> config miu select [70] [ef] [ef] [ef].
    <USB>[UDC] PULL DOWN D+.
    <USB>[UDC] PULL UP D+.
    <USB>[GADGET] UDC start
    <USB>[UDC] PULL UP D+.
    <USB>[LINK] High speed device.
    <USB>[2][EN] bulk out with maxpacket/fifo(512/1024)
    <USB>[1][EN] bulk in with maxpacket/fifo(512/8192)
    
  2. 双击sstar_fastboot_flashall.bat完成接下来的烧录

3.4 AB设备无法启动处理方法

异常情况的处理主要还是结合3.2的流程图,主要是靠几个机制来保证出现异常时可以刷机救砖。

  • misc分区中的AB metadata被损坏时,会重新初始化并设置当前slot为slot A。
  • 没有slot可用,会尝试从slot a启动起到fastboot模式。
  • U-boot启动过程中可以通过串口敲回车听到U-boot console,可以敲fastboot 0命令进fastboot模式烧录。
  • 所有slot的PL_PRE.bin和bootloader.img中镜像损坏无法正常加载时会halt住,可以用flashtool烧录。
  • 切boot jumping到USB模式用空片烧录工具烧录。

需要明确的是:

  • retry_count只会用来限制还没成功启动Android系统的的slot,也就是一旦slot被标记成successful_boot,将不再有retry_count限制当前slot可以尝试启动的次数。
  • mark_current_slot_unbootable的动作只会镜像加载失败时发生,只有在读镜像IO error(load fail)和镜像非法(sub-image invalid)会有动作。而判断镜像是否合法的方式一般是校验镜像头部的magic,在secureboot使能后,secureboot保护的镜像会做hash校验。