Bootloader_AB分区说明
1. 概述¶
本文旨在介绍SigmaStar平台实现Android AB分区特性的细节。其中包括在SigmaStar Android平台上开启AB分区的配置说明、烧录说明、异常情况的处理、AB分区启动代码流程等。阅读本文前,请至少了解如下内容,下文会简单说明:
- SigmaStar的分区配置方法、Fstab配置方法。
- 原生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>
,镜像烧录先后顺序大致如下:
- 烧录GPT(fastboot flash gpt partition_table.img),更新板子上的分区表,为后面烧录镜像提供分区位置支持。
- 烧录IPL_PRE.bin到BOOT1硬件分区(fastboot flash BOOT1 IPL_PRE.bin),fastboot flash命令流程会对BOOT1或BOOT2这个分区做特殊处理,将传递过来的镜像烧录到eMMC的BOOT1或BOOT2硬件分区
- 烧录其他镜像。(
fastboot flash <partition_name> <partition_name>.img
)
对于其他的烧录方式,可能不需要硬性规定镜像烧录顺序,需要注意的是IPL_PRE.bin要烧录到BOOT1和BOOT2硬件分区。
3.3.2 空片烧录示例¶
下面举例空片烧录如何使用flashtool搭配fastboot脚本完成烧录(非空片下也可以使用此方法):
-
空片状态的板子可以看到类似如下log,此时因为是空片,板子当前HALT在ROM:
E:CD HDR ERR 0000e000 HDR ERR 0000e001 HDR ERR 0000e002
-
因为是空片状态,所以要先烧录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勾选的配置不同之处已经圈出。
-
当板子至少有了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)
-
双击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校验。