Bootloader overview

A bootloader is a vendor-proprietary image responsible for bringing up the kernel on a device. The bootloader guards the device state and is responsible for initializing the Trusted Execution Environment (TEE) and binding its root of trust. The bootloader also verifies the integrity of the boot and recovery partitions before moving execution to the kernel.

Example bootloader flow

Here's an example bootloader flow:

  1. Load and initialize memory.

  2. Verify the device according to Verified Boot flow.

  3. Verify the boot partitions, including boot, dtbo, init_boot, and recovery, according to the Verified Boot flow. As part of this step, check the boot image header version and parse the header accordingly.

  4. If A/B updates are used, determine the current slot to boot.

  5. Determine if recovery mode should be booted. For more information, see Supporting OTA Updates.

  6. Load the boot images, such as boot.img, vendor_boot.img, init_boot.img, and other proprietary vendor boot images. These boot images contain the kernel and ramdisk images.

    1. Load the kernel into memory as a self-executable compressed binary. The kernel decompresses itself and starts executing into memory.

    2. Load ramdisks and the bootconfig section into memory to create initramfs.

Additional bootloader-related features

Following is a list of additional bootloader-related features that you can implement:

  • Device tree overlay (DTO). A device tree overlay lets the bootloader to support different hardware configurations. A DTO is compiled into a device tree blob (DTB) which is used by the bootloader.

  • Kernel image virtual address randomization. The bootloader supports randomizing the virtual address at which the kernel image is loaded. To randomize the address, set RANDOMIZE_BASE to true in the kernel config. The bootloader must provide entropy by passing a random u64 value in the /chosen/kaslr-seed device tree node.

  • Verified Boot. Verified Boot lets the bootloader to ensure all executed code comes from a trusted source.

  • Boot config. Boot config is available in Android 12 and higher and is a mechanism for passing configuration details from the build and bootloader to the operating system. Prior to Android 12, kernel command-line parameters with the prefix of androidboot are used.

  • Over-the-air (OTA) updates. Android devices in the field can receive and install OTA updates to the system, app software, and time zone rules. This feature has implications on your bootloader implementation. For general information on OTA, see OTA updates. For bootloader-specific OTA implementation details, see Supporting OTA updates.

  • Version binding. Version binding binds security keys to the operating system and patch level version. Version binding ensures that an attacker who discovers a weakness in an old version of the system or the TEE software can't roll a device back to the vulnerable version and use keys created with the newer version. The bootloader must provide certain information to support version binding. For further information, see Version information in AVB properties.

Kernel command line

Concatenate the kernel command line from the following locations:

  • Bootloader command line: set of static and dynamic parameters determined by the bootloader

  • Device tree: from the chosen/bootargs node

  • defconfig: from CONFIG_CMDLINE

  • boot.img: from the command line (for offsets and sized, refer to system/core/mkbootimg/bootimg.h

As of Android 12, for androidboot.* parameters that we need to pass to Android userspace, we can use bootconfig instead of the kernel command line.