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 tosystem/core/mkbootimg
. The bootloader reads thebootimg.h
header file generated bymkbootimg
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
, orImage.gz
) and can be flashed independently, combined with ramdisk images, flashed to theboot
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 usingmkbootfs
then flashed into the boot partition.File system. These images include
system
,userdata
, andrecovery
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.
For details, refer to
system/core/libsparse/sparse_format.h
.For the implementation, refer to
system/core/libsparse/sparse_read.cpp
.
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
.