映像

引导加载程序依赖于以下映像。

  • 启动。这些映像包含通过未经修改的 mkbootimg(如需了解实现,请参阅 system/core/mkbootimg)组合在一起的内核和 ramdisk 映像。引导加载程序会读取 mkbootimg 生成的 bootimg.h 头文件,并更新内核标头,使其包含被刷写的 ramdisk 的正确位置和大小、内核基址、命令行参数以及其他内容。然后,引导加载程序会将启动映像中指定的命令行附加到引导加载程序生成的命令行的末尾。

  • 内核。这些映像采用标准 Linux 格式(如 zImageImageImage.gz),可以单独刷写,可以与 ramdisk 映像相结合,可以刷写到 boot 分区,也可以从内存启动。在创建内核映像时,建议使用连接的设备树二进制文件(而不是为设备树使用一个单独的分区)。为不同的电路板修订版本使用多个设备树 Blob (DTB) 时,应按电路板修订版本降序连接多个 DTB。

  • Ramdisk。这些映像包含适合作为 rootfs 装载的根文件系统。它们先通过 mkbootfs 与内核映像组合在一起,然后再刷写到启动分区中。

  • 文件系统。这些映像包括 systemuserdatarecovery 映像,必须采用 Yaffs2 格式或稀疏映像格式。

映像格式

文件系统映像可以采用 Yaffs2 格式或稀疏映像格式。

Yaffs2

使用原始 NAND 存储空间的设备必须使用由未经修改的 mkyaffs2image 生成的 Yaffs2 格式的映像(在 AOSP 中,请参阅 external/yaffs2/yaffs2/utils。引导加载程序负责使用这些映像,并将 yaffs 额外数据转移到给定 NAND 硬件的带外区域中的适当位置。如果需要软件 ECC,引导加载程序还应在此时执行相应的计算。

如需详细了解映像格式,请参阅 Yaffs 2 规范

稀疏

所有 Android 设备都应支持稀疏映像格式。

使用基于块的存储空间的设备应支持 ext4f2fs。如需快速传输并刷写大型空 ext4 文件系统(如 userdata),应以稀疏格式存储映像,映像中包含有关文件系统的哪些区域可以保留不写的信息。

映像格式

稀疏映像格式包含一个文件标头,后跟一系列区块。文件标头、区块标头和区块数据是 4 个字节的倍数,并且所有字段都采用无符号的小端字节序。

文件标头采用以下格式:

  • 32 位魔数:0xed26ff3a
  • 16 位主要版本 (0x1) - 拒绝更高主要版本的映像
  • 16 位次要版本 (0x0) - 允许更高次要版本的映像
  • 以字节为单位的 16 位文件标头大小(在 v1.0 中为 28 位)
  • 以字节为单位的 16 位区块标头大小(在 v1.0 中为 12 位)
  • 以字节为单位的 32 位块大小,必须是 4 的倍数
  • 输出文件中的 32 位块总大小
  • 输入文件中的 32 位区块总大小
  • 原始数据的 32 位 CRC32 校验和,将“随意”类型算作 0 标准 802.3 多项式(使用公共域表实现)。

文件区块采用以下格式:

  • 16 位区块类型:
    • 0xCAC1 原始类型(后跟以块为单位的大小 * 以字节为单位的块大小)
    • 0xCAC2 填充类型(后跟 4 个字节的填充数据)
    • 0xCAC3 随意类型(后跟 0 个字节)
  • 16 位保留(写入为 0,读取时忽略)
  • 输出映像中以块为单位的 32 位区块大小
  • 区块输入文件中以字节为单位的 32 位总大小(包括区块标头和数据)

创建稀疏映像

您可以使用 mke2fs 实用程序创建采用稀疏映像格式的映像(这也是用于创建引导加载程序读取和刷写的映像的工具)。

实现写入程序

mke2fs 实用程序知道需要写入映像的哪些区域,并对这些区域之间的“随意”区块进行编码。另一个工具 img2simg 会将非稀疏映像转换为稀疏映像。常规映像没有关于“随意”区域的信息,转换过程至多能做到的是查找重复数据块,以减小所生成映像的大小。

实现读取程序

读取程序应拒绝主要版本未知的映像,但应接受次要版本未知的映像。读取程序可能会拒绝具有其不支持的区块大小的映像。主要版本经过验证后,读取程序应忽略具有未知类型字段的区块,使用“文件中的区块大小”跳过文件中的区块,并跳过输出中的“以块为单位的区块大小”块。

应针对写入磁盘的数据计算循环冗余校验 (802.3 CRC32)。任何未写入的区域(随意区域或跳过的区块)都应在 CRC 中算作 0。应将写入或跳过的总块数与标头中的“总块数”字段进行比较。simg2img 工具会将稀疏映像格式转换为标准映像格式,这样会丢失稀疏信息。

刷写映像

除非主机 fastboot 工具先发送 erase 命令,否则 flash 命令不得清空分区。这样的话,便可以使用多个以“跳过”块开始的稀疏映像刷写非常庞大的分区(包含多个较小的区块),以寻找并跳过已经写入的区域。按需创建这些映像的任务已由 fastboot 主机端工具处理。

在解锁模式下刷写之前,应对无线装置和引导加载程序映像进行健全性检查。例如,与从 build 创建的 android-info.txt 进行比较并确认版本匹配。此外,还应在刷写时检查引导加载程序映像签名,以确保它在启动(可能包括防回滚功能)过程中能够通过验证。

在 Google 品牌设备上,从首款以商业形式推出的引导加载程序开始,刷写到较低版本的引导加载程序应能够正常工作。如需详细了解 fastboot 协议,请参阅 system/core/fastboot/README.md