Android Boot Image

作者 by adtxl / 2022-03-14 / 暂无评论 / 549 个足迹

翻译自https://u-boot.readthedocs.io/en/v2021.07/android/boot-image.html

1. 简介

Android的boot镜像用于启动Android系统,一般包含kernel image(如 zImage文件)和ramdisk.有时也包含一些额外的二进制文件。该image是AOSP编译出来的,也就是boot.img文件,被烧到emmc中的boot分区。Bootloader会将image从boot分区中加载到ram中,并从中启动kernel。然后kernel从ramdisk中启动init进程。需要提醒的是,recovery.img和Android Boot Image具有相同的格式

Android Boot Image的格式如在参考文献[1]中所述。目前它可以有以下几种image headers:

  • v0:这种被称为老的boot image header,用于Android 9以前的设备。包含kernel image,ramdisk和第二阶段的bootloader(一般不使用这玩意).
  • v1:用于搭载Android9的设备,添加recovery_dtbo字段,在非A/B设备的recovery.img中使用。(详情见参考文献[2])
  • v2:用于搭载Android10的设备,添加了dtb字段,引用了包含DTB blob的有效负载。(可以是一个接着一个,或者是Android DTBO image format)

v2、v1 和 v0 格式向后兼容。

Android Boot Image格式在u-boot中由结构体struct addr_img_hdr描述,在头文件include/android_image.h中。u-boot支持启动Android Boot Image,并且支持一些相关的命令。

2. 启动

在uboot中,可以使用bootm命令从Android Boot Image中启动Android操作系统。为了支持Android Boot Image格式,uboot需要有以下config,

CONFIG_ANDROID_BOOT_IMAGE=y

然后就可以使用bootm命令启动Android,如下所示:

=> bootm $loadaddr $loadaddr $fdtaddr

其中,$loadaddr表示boot image在ram中的加载地址,$fdtaddr表示dtb在ram中的加载地址。

相应的参数:

  1. kernel image在ram中的位置
  2. ramdisk在ram中的位置(如果不适用,可以是"-"
  3. dtb在ram中的位置

bootm命令会确认位于$loadaddr地址的Android Boot image的format,并从中解析然后启动kernel,将dtb的地址提供给kernel(从第三个参数),通过dtb将有关ramsiak的信息传递给kernel.

3. DTB和DTBO

bootm命令不能只是用Android Boot Image(dtb 字段)中的dtb,有下面几个原因:

  • v2之前的Android Boot Image中没有dtb字段
  • 在DTB区域中可能有多个dtb(如,针对不同的SOC)
  • 某些dtbo需要在启动之前merge到dtb中

所以,用户必须手动准备dtb blob,并且作为bootm的第三个参数。可以使用下面的几个命令来执行此操作:

  1. aboot.img: 操纵Android Boot Image,允许从中提起meta-information和有效负载(payloads)
  2. adtimg: 操纵Android DTB/DTBO image, 允许从中提取DTB/DTBO。

为了使用这些命令,需要添加下面两个config,

CONFIG_CMD_ABOOTIMG=y
CONFIG_CMD_ADTIMG=y

例如,我们假设某款设备在emmc上的Android 分区如下所示:

  • boot: 包含Android Boot Image v2(包含DTB blobs)
  • dtbo: 包含 DTBO blobs

那么使用下面一系列的命令可以启动Android:

=> mmc dev 1

   # Read boot image to RAM (into $loadaddr)
=> part start mmc 1 boot boot_start
=> part size mmc 1 boot boot_size
=> mmc read $loadaddr $boot_start $boot_size

   # Read DTBO image to RAM (into $dtboaddr)
=> part start mmc 1 dtbo dtbo_start
=> part size mmc 1 dtbo dtbo_size
=> mmc read $dtboaddr $dtbo_start $dtbo_size

   # Copy required DTB blob (into $fdtaddr)
=> abootimg get dtb --index=0 dtb0_start dtb0_size
=> cp.b $dtb0_start $fdtaddr $dtb0_size

   # Merge required DTBO blobs into DTB blob
=> fdt addr $fdtaddr 0x100000
=> adtimg addr $dtboaddr
=> adtimg get dt --index=0 $dtbo0_addr
=> fdt apply $dtbo0_addr

   # Boot Android
=> bootm $loadaddr $loadaddr $fdtaddr

此操作应用于 Android 10 启动。当然,整个 Android 启动过程包括更多的操作,例如:

  • 从BCB获取启动原因(参考文献[4])
  • 实现recovery boot
  • 实现fastboot引导
  • 实现A/B slotting(参考文献[5])
  • 实现AVB 2.0(参考文献[6])

4. C API

int android_image_get_kernel(conststruct andr_img_hdr *hdr, int verify, ulong *os_data, ulong *os_len)

处理Android boot image中的kernel部分

  • 参数

const struct andr_img_hdr *hdr
Pointer to image header, which is at the start of the image.

int verify
Checksum verification flag. Currently unimplemented.

ulong *os_data
Pointer to a ulong variable, will hold os data start address.

ulong *os_len
Pointer to a ulong variable, will hold os data length.

  • 描述:

该函数返回操作系统image的起始地址和长度。此外,它将kernel command line附件到bootargs环境变量中。

This function returns the os image’s start address and length. Also, it appends the kernel command line to the bootargs env variable.

  • 返回值

Zero, os start address and length on success,
otherwise on failure.

bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size)¶

获取recovery DTBO image的地址和大小

  • 参数

ulong hdr_addr
Boot image header address

ulong *addr
If not NULL, will contain address of recovery DTBO image

u32 *size
If not NULL, will contain size of recovery DTBO image

  • 描述

从recovery.img中提取dtbo的地址和长度,一旦获取后就可以使用adtimg命令后者android_dt_*()函数提取需要的dtbo.

这个dtbo只在非A/B设备中需要,并且只存在与recovery镜像中。在A/B设备中,我们总是可以依赖dtbo分区。

Get the address and size of DTBO image in “Recovery DTBO” area of Android Boot Image in RAM. The format of this image is Android DTBO (see corresponding “DTB/DTBO Partitions” AOSP documentation for details). Once the address is obtained from this function, one can use adtimg U-Boot command or android_dt_*() functions to extract desired DTBO blob.

This DTBO (included in boot image) is only needed for non-A/B devices, and it only can be found in recovery image. On A/B devices we can always rely on “dtbo” partition. See “Including DTBO in Recovery for Non-A/B Devices” in AOSP documentation for details.

  • 返回值

true on success or false on error.

bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr)¶

获取boot.img中dtb区域的地址

  • 参数

ulong hdr_addr
Boot image header address

ulong *addr
Will contain the address of DTB area in boot image

  • 返回值

true on success or false on fail.

bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr, u32 *size)¶

Get address and size of blob in DTB area.

  • 参数

ulong hdr_addr
Boot image header address

u32 index
Index of desired DTB in DTB area (starting from 0)

ulong *addr
If not NULL, will contain address to specified DTB

u32 *size
If not NULL, will contain size of specified DTB

  • 返回值

Get the address and size of DTB blob by its index in DTB area of Android Boot Image in RAM.

Return

true on success or false on error.

void android_print_contents(conststruct andr_img_hdr *hdr)

prints out the contents of the Android format image

  • 参数

const struct andr_img_hdr *hdr
pointer to the Android format image header

  • 描述

android_print_contents() formats a multi line Android image contents description. The routine prints out Android image properties

  • 返回值

no returned results

bool android_image_print_dtb_info(conststruct fdt_header *fdt, u32 index)

Print info for one DTB blob in DTB area.

  • 参数

const struct fdt_header *fdt
DTB header

u32 index
Number of DTB blob in DTB area.

  • 返回值

true on success or false on error.

bool android_image_print_dtb_contents(ulong hdr_addr)

Print info for DTB blobs in DTB area.

  • 参数

ulong hdr_addr
Boot image header address

  • 描述

DTB payload in Android Boot Image v2+ can be in one of following formats:

  • Concatenated DTB blobs(连接的dtb)
  • Android DTBO format (see CONFIG_CMD_ADTIMG for details)

This function does next:

  • Prints out the format used in DTB area

  • Iterates over all DTB blobs in DTB area and prints out the info for each blob.

  • 返回值

true on success or false on error.

5. 参考

[1] https://source.android.com/devices/bootloader/boot-image-header
[2] https://source.android.com/devices/bootloader/recovery-image
[3] https://source.android.com/devices/architecture/dto/partitions
[4] https://u-boot.readthedocs.io/en/v2021.07/android/bcb.html
[5] https://u-boot.readthedocs.io/en/v2021.07/android/ab.html
[6] https://u-boot.readthedocs.io/en/v2021.07/android/avb2.html
[7] https://source.android.com/devices/bootloader
[8] https://connect.linaro.org/resources/san19/san19-217/

独特见解