Google is committed to advancing racial equity for Black communities. See how.

Images

The bootloader relies upon the following images.

  • Boot. These images contain a kernel and ramdisk image combined using an unmodified mkbootimg (for the implementation, refer to system/core/mkbootimg. The bootloader reads the bootimg.h header file generated by mkbootimg and updates the kernel header to contain the correct location and size of the ramdisk in flash, base address of the kernel, command line parameters, and more. The bootloader then appends the command line specified in the boot image to the end of the bootloader-generated command line.

  • Kernel. These images use a standard Linux format (such as zImage, Image, or Image.gz) and can be flashed independently, combined with ramdisk images, flashed to the boot partition, or booted from memory. When creating kernel images, concatenated device-tree binaries are recommended (instead of a separate partition for the device tree). When using multiple device tree blobs (DTBs) for different board revisions, concatenate multiple DTBs in descending order of board revision.

  • Ramdisk. These images contain a root file system suitable for mounting as a rootfs. They are combined with kernel images using mkbootfs then flashed into the boot partition.

  • File system. These images include system, userdata, and recovery images and must use Yaffs2 format or sparse image format.

Image formats

File system images can be Yaffs2 format or sparse image format.

Yaffs2

Devices using raw NAND storage must use images in Yaffs2 format generated by an unmodified mkyaffs2image (in AOSP, refer to external/yaffs2/yaffs2/utils. The bootloader is responsible for consuming these images and relocating the yaffs extra data into the appropriate location in the out-of-band area for the given NAND hardware. If software ECC is required, the bootloader should also do that computation at this time.

For details on the image format, refer to the Yaffs 2 Specification.

Sparse

All Android devices should support the sparse image format.

Devices using block-based storage should support ext4 or f2fs. To quickly transfer and flash large, empty ext4 file systems (such as userdata), store the image in a sparse format that contains information about which areas of the file system can be left unwritten.

Image format

The sparse image format contains a file header, followed by a series of chunks. The file header, chunk header, and chunk data are multiples of 4 bytes, and all fields are unsigned little-endian.

The file header uses the following format:

  • 32-bit magic: 0xed26ff3a
  • 16-bit major version (0x1) - reject images with higher major versions
  • 16-bit minor version (0x0) - allow images with higher minor versions
  • 16-bit file header size in bytes (28 in v1.0)
  • 16-bit chunk header size in bytes (12 in v1.0)
  • 32-bit block size in bytes, must be multiple of 4
  • 32-bit total blocks in output file
  • 32-bit total chunks in input file
  • 32-bit CRC32 checksum of original data, counting "don't care" as 0 Standard 802.3 polynomial (using a public domain table implementation).

A file chunk uses the following format:

  • 16-bit chunk type:
    • 0xCAC1 raw (followed by size in blocks * block size in bytes)
    • 0xCAC2 fill (followed by 4 bytes of fill data)
    • 0xCAC3 don't care (followed by 0 bytes)
  • 16 bits reserved (write as 0, ignore on read)
  • 32-bit chunk size in blocks in output image
  • 32-bit total size in bytes of chunk input file including chunk header and data

Creating sparse images

You can use the mke2fs utility to create images in sparse image format (this is also the tool used to create the images the bootloader reads and flashes).

Implementing the writer

The mke2fs utility knows what areas of the image need to be written and encodes "don't care" chunks between them. Another tool, img2simg, converts non-sparse images to sparse images. Regular images have no information about "don't care" areas; the best a conversion can do is look for blocks of repeated data to reduce the resulting image size.

Implementing the reader

Readers should reject images with unknown major versions but accept images with unknown minor versions. Readers might reject images with chunk sizes they don't support. Ater the major version is validated, the reader should ignore chunks with unknown type fields, skipping over the chunk in the file using the "chunk size in file" and skipping "chunk size in blocks" blocks on the output.

A cyclic redundancy check (802.3 CRC32) should be calculated for the data that is written to disk. Any area that isn't written (don't care, or a skipped chunk), should be counted as 0s in the CRC. The total number of blocks written or skipped should be compared against the "total blocks" field in the header. The tool simg2img converts the sparse image format to a standard image, which loses the sparse information.

Flashing images

The flash command shouldn't erase the partition unless the host fastboot tool sends an erase command first. This allows flashing a very large partition in multiple smaller chunks using multiple sparse images that start with a "skip" block to seek over the already-written area. Creating these images on demand is already handled by the fastboot host side tool.

Sanity checks should be done on radio and bootloader images prior to flashing in unlocked mode. For examples, compare to android-info.txt created from the build and confirm the version matches. Also check bootloader image signature at flash time to make sure it passes validation during boot (which might include antirollback features).

On Google-branded devices, flashing to older versions of bootloaders should work properly, starting from the first commercially-shipped bootloader. For details on the fastboot protocol, refer to system/core/fastboot/README.md.