bootloader

Bootloader Overview

The bootloader is a vendor-proprietary image that is responsible for launching the kernel on the device. The bootloader monitors 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  and  partitions before moving execution to the kernel. bootrecovery

Bootloader flow example

Here is an example of the bootloader flow:

  1. Load and initialize memory.

  2. Verify the device according tothe boot-time verification process.

  3. Verify the boot partition according to the boot-time verification process, including boot, dtbo, init_boot and < a i=4>. During this step, check theboot image header version and parse the header accordingly. recovery

  4. If using A/B update, determines the current slot to start.

  5. Determines whether recovery mode should be initiated. For more information, seeSupporting OTA updates.

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

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

    2. Load the ramdisk and bootconfig sections into memory to create initramfs.

Other features related to bootloader

Listed below are other bootloader-related features you can implement:

  • Device Tree Overlay (DTO). With thedevice tree overlay the bootloader can support different hardware configurations. The DTO is compiled into the device tree blob (DTB) used by the bootloader.

  • Kernel image virtual address randomization. The bootloader supports randomization of the virtual addresses where kernel images are loaded. To randomize addresses, set RANDOMIZE_BASE to true in the kernel configuration. The bootloader must provide entropy by passing a random u64 value in the /chosen/kaslr-seed device tree node.

  • Verify on startup. Withboot-time verification the bootloader ensures that all executed code comes from a trusted source.

  • Start configuration. Launch configurationAvailable in Android 12 and later, is a mechanism for passing configuration details from the build and bootloader to the operating system. Prior to Android 12, the system used kernel command line parameters prefixed with androidboot .

  • Over-the-air (OTA) updates. Working Android devices can receive and install OTA updates for system, application software, and time zone rules. This feature has an impact on bootloader implementation. For general information about OTAs, see OTA updates. For more information about the bootloader related OTA implementation, seeSupporting OTA Updates.

  • version binding. Version BindingBind security keys to operating system and patch level versions. Version bundling ensures that an attacker who discovers a vulnerability in an older version of the system or TEE software cannot roll the device back to a vulnerable version or use keys created in a newer version. The bootloader must provide certain information to support version binding. For more information, see Version information in AVB properties.

kernel command line

Concatenate the kernel command line from:

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

  • Device tree: From chosen/bootargs node

  • defconfig:from CONFIG_CMDLINE

  • boot.img: From the command line (for offsets and sizes, see system/core/mkbootimg/bootimg.h)< /span>

Starting from Android 12, for the androidboot.* parameters that need to be passed to the Android user space, we can use bootconfig instead of the kernel command line.

Normalized start reason

Android 9 makes the following changes to the bootloader launch reason specification.

Start reason

The bootloader uses dedicated hardware and memory resources to determine why the device rebooted, and then adds androidboot.bootreason=<reason> to the Android kernel command line used to boot the device to communicate this One judgment. init then transforms this command line and propagates it into Android properties bootloader_boot_reason_prop (ro.boot.bootreason). For devices shipping with Android 12 or higher (kernel version 5.10 or higher), androidboot.bootreason=<reason> is added to the bootconfig instead of the kernel command line.

Startup reason specification

The startup reason specified in previous versions of Android has the following format: no spaces, all lowercase letters, and very few requirements (e.g. reporting kernel_panic, watchdog, cold/warm/hard), and other special reasons are allowed. This loose specification resulted in hundreds or thousands of custom boot reason strings (sometimes meaningless), creating an unmanageable situation. Until the latest Android releases, the dramatic increase in nearly unparseable or meaningless content submitted by bootloaders has created compliance issues for bootloader_boot_reason_prop .

While developing the Android 9 version, the Android team discovered that the content in the old bootloader_boot_reason_prop would increase dramatically and could not be rewritten while the system was running. Therefore, any improvements to the boot cause specification will require interaction with bootloader developers and adjustments to the existing system. To this end, the Android team has taken the following steps:

  • Engage with bootloader developers and encourage them to:
    • Provide bootloader_boot_reason_prop with a canonical, parsable, and identifiable reason.
    • Add content to the system/core/bootstat/bootstat.cpp kBootReasonMap list.
  • Add controlled system_boot_reason_prop (sys.boot.reason) source code that can be rewritten while the system is running. Only a small number of system apps (such as bootstat and init) can override this property, but all apps can read it by obtaining the sepolicy permission.
  • Inform the user of the startup reason and let them wait until the userdata partition is loaded before trusting the content in the system startup reason attribute system_boot_reason_prop .

Why did you wait so long? Although bootloader_boot_reason_prop is available early in the boot process, it is blocked by Android security policy as required because it represents inaccurate, unparseable, and non-conforming information. In most cases, only developers with in-depth knowledge of the boot system will need access to this information. Only after the userdata partition is loaded can it be accurately and reliably extracted through  that is optimized, parsable and compliant The startup reason API. Specifically:system_boot_reason_prop

  • Before the userdata partition is loaded,  will contain  value in . system_boot_reason_propbootloader_boot_reason_prop
  • After the userdata partition is mounted, it can be updated  to make it comply with requirements or to report updates accurate information. system_boot_reason_prop

For the reasons stated above, Android 9 increases the period of time you need to wait before you can officially obtain the launch reason, changing it from being immediately accurate on launch (using bootloader_boot_reason_prop). Available only after the userdata partition has been mounted (using system_boot_reason_prop).

Bootstat logic relies on a more informative and compliant bootloader_boot_reason_prop. When this attribute uses a predictable format, it improves accuracy for all controlled restart and shutdown situations, thereby optimizing and extending the accuracy and meaning of system_boot_reason_prop .

Standardized startup reason format

In Android 9, the canonical launch reason format for bootloader_boot_reason_prop uses the following syntax:

<reason>,<subreason>,<detail>…

The formatting rules are as follows:

  • lower case
  • No spaces (underscores allowed)
  • All printable characters
  • Comma-separated reason, subreason, and one or more detail.
    • Required reason, indicating the highest priority reason why the device must be restarted or shut down.
    • Optional subreason, a brief summary of why the device had to be restarted or shut down (or the person who restarted/shut down the device).
    • One or more optional detail values. detail can point to a subsystem to help determine which specific system is causing subreason . You can specify multiple detail values, which should generally be ordered by importance. However, it is possible to report multiple detail values ​​of equal importance.

is considered illegal if bootloader_boot_reason_prop is empty (as this would allow other agents to add a startup reason after the fact).

reason required

The value specified for for reason (the first span, before the terminator or comma) must be one of the following sets (divided into kernel reasons, strong reasons, and weak reasons) :

  • Kernel set:
    • "watchdog"
    • "kernel_panic"
  • Strong set:
    • "recovery"
    • "bootloader"
  • Weak set:
    • "cold": Usually means a complete reset of all devices, including memory.
    • "hard": Usually indicates that the hardware reset the state, and ramoops should retain persistent content.
    • "warm": Typically indicates that memory and devices remain in some state, and ramoops (see the pstore driver in the kernel) the backing store contains persistence content.
    • "shutdown"
    • "reboot": Usually means ramoops status and hardware status are unknown. This value is the same generic value as cold, hard and warm and provides a hint as to how deeply the device has been reset.

The bootloader must provide a kernel set or a weak set reason, it is strongly recommended that the bootloader provide subreason if this can be determined. For example, the startup reason for a long press of the power button (regardless of ramoops backup) is "reboot,longkey".

The first span reason cannot be part of any subreason or detail . However, since kernel set causes cannot be generated by userspace, "watchdog" may be reused after weak set causes along with source code details (e.g. "reboot,watchdog,service_manager_unresponsive" or a> "reboot,software,watchdog").

The activation reason should be interpretable without expert internal knowledge and/or should be human understandable and provide intuitive reporting. Examples: "shutdown,vbxd" (bad), "shutdown,uv" (better), "shutdown,undervoltage" (preferred).

"Cause-Sub-Cause" Combination

Android reserves a set of reason-subreason combinations that should not be overused under normal use; however, if the combination accurately reflects Relevant situations can be used according to specific circumstances. Examples of reserved combinations include:

  • "reboot,userrequested"
  • "shutdown,userrequested"
  • "shutdown,thermal"(上人 thermald
  • "shutdown,battery"
  • "shutdown,battery,thermal"(上人 BatteryStatsService
  • "reboot,adb"
  • "reboot,shell"
  • "reboot,bootloader"
  • "reboot,recovery"

For more information, see  in system/core/bootstat/bootstat.cpp and the associated git changelog records in the Android source code repository. kBootReasonMap

Report start reason

All boot reasons (whether from the bootloader or recorded in the canonical boot reasons) must be documented in the  section of system/core/bootstat/bootstat.cpp .  The list contains various compliance reasons and legacy reasons for noncompliance. Bootloader developers should only register new compliance reasons here (non-compliance reasons should not be registered unless the product has shipped and cannot be changed). kBootReasonMapkBootReasonMap

Note: Although system/core/bootstat/bootstat.cpp contains a kBootReasonMap section that lists a number of legacy reasons, these reasons The presence of does not mean that the reason string is permitted for use. Compliance reasons are listed in a subset of this list; this subset is expected to grow as bootloader developers continue to register and document more compliance reasons.

It is strongly recommended to use existing compliant entries in system/core/bootstat/bootstat.cpp and to restrict the use of non-compliant strings. Please see the following guidelines:

  • Allow to report from the bootloader "kernel_panic" because bootstat may be able to check kernel_panic signatures of ramoops in order to optimize the sub-cause to canonical system_boot_reason_prop.
  • Not allowed Non-compliant reporting as kBootReasonMap (e.g. "panic")) from the bootloader string, as this will ultimately lead to failure to optimize reason.

For example, if kBootReasonMap contains "wdog_bark", the bootloader developer should take the following actions:

  • Change to "watchdog,bark" and add it to the list in kBootReasonMap .
  • Consider what "bark" means to someone unfamiliar with the technology, and determine whether there is a subreason that makes more sense.

Verify launch reason compliance

Currently, Android does not provide active CTS tests that can accurately trigger or check for all launch reasons a bootloader may provide; partners can still attempt to run passive tests to determine compatibility.

Therefore, to achieve bootloader compliance, bootloader developers need to voluntarily adhere to the spirit of the above rules and guidelines. We would urge such developers to contribute to AOSP (especially system/core/bootstat/bootstat.cpp) and use this opportunity as a forum to discuss launch reason issues.

boot image header

Android 9 introduces a version field in the boot image header file to update the header file while maintaining backward compatibility. The bootloader must check the header version field and parse the header file. If the device:

  • Released with Android 13, you can use launch header version 3 or 4. For devices supporting the Generic Kernel Image (GKI) architecture, version 4 is the primary boot image and  field must be zero. The device bootloader should obtain version information from the Android Verification at Boot (AVB) properties.
  • Released with Android 12, you can use launch header version 3 or 4. Version 4 is the primary boot image for devices that support the Generic Kernel Image (GKI) architecture.
  • Released with Android 11, you can use launch header version 3. This version must be used for the main boot image for devices that support the Generic Kernel Image (GKI) architecture.
  • If running Android 10, you must use launch header version 2.
  • If running Android 9, you must use launch header version 1.
  • If running Android 8 and below, it is considered to be using boot image header version 0.

For all devices running Android 9 or higher, Vendor Test Suite (VTS) checks boot/recovery The format of the image to ensure that the version used by the boot image header file is correct. For AOSP details about all currently supported boot image headers and vendor boot image headers, see system/tools/mkbootimg/include/bootimg/bootimg.hsystem/tools/mkbootimg/include/bootimg/bootimg.h a>.

Implement boot image header file version number

mkbootimg The tool accepts the following parameters.

parameter illustrate
header_version Set the boot image header file version. If the header file version is:
  • 1 or 2, the boot image supports DTBO recovery image or ACPIO recovery image.
  • 3. The boot image does not support recovery images.
recovery_dtbo is suitable for architectures using DTB. Specify the path to the DTBO recovery image. This parameter is optional for A/B devices that do not require recovery images. If a non-A/B device uses header_version as:
  • 1 or 2, the device can specify this path, or you can use the recovery_acpio section to specify the path to the ACPIO recovery image.
  • 3, the device cannot specify a DTBO recovery image.
recovery_acpio is for architectures using ACPI instead of DTB. Specify the path to the ACPIO recovery image. This parameter is optional for A/B devices that do not require recovery images. If a non-A/B device uses header_version as:
  • 1 or 2, the device can specify this path, or you can use the recovery_dtbo section to specify the path to the DTBO recovery image.
  • 3, the device cannot specify an ACPIO recovery image.
dtb Path to the DTB image in the boot/recovery image.
dtb_offset When is added to the base parameter, the system provides the actual loading address of the final device tree. For example, if the base parameter is 0x10000000 and the dtb_offset parameter is 0x01000000, the boot image header file The dtb_addr_field will be populated with 0x11000000.

Device BoardConfig.mk uses BOARD_MKBOOTIMG_ARGS configuration to add header version to mkbootimg motherboard-specific other parameters. For example:

BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)

The Android build system uses BoardConfig variables BOARD_PREBUILT_DTBOIMAGE to set during recovery image creation mkbootimg of the tool < a i=4> parameter. To learn more about the changes to the Android Open Source Project (AOSP), see the list of changesrelated to boot image header version numbers. recovery_dtbo

Boot image header version 4

Android 12 provides a boot_signature in boot image header version 4 that can be used to check the integrity of the kernel and ramdisk. This check is done in VtsSecurityAvbTest and is required for devices using the GKI architecture. However, boot_signature is not involved in the device-specific boot-time verification process and is only used in VTS. For details, see GKI boot.img development board configuration and GKI boot-time verification settings >.

Vendor boot image headersVersion 4 supports multiple vendor ramdisk fragments.

Boot image header version 4 has the following format.

struct boot_img_hdr
{
#define BOOT_MAGIC_SIZE 8
    uint8_t magic[BOOT_MAGIC_SIZE];

    uint32_t kernel_size;    /* size in bytes */
    uint32_t ramdisk_size;   /* size in bytes */

    uint32_t os_version;

    uint32_t header_size;    /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint32_t header_version; /* offset remains constant for version check */

#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
    uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];

    uint32_t signature_size; /* size in bytes */
};

Boot image header version 3

Android 11 updates the boot image headers to version 3, which removes the following data:

  • Second stage bootloader. The second_size and second_addr fields are no longer displayed in the boot image header file. Devices with second-stage bootloaders must store the corresponding bootloader in its own partition.

  • Restore Image. The requirements for specifying recovery images have been deprecated and no longer appear in the boot image header file recovery_dtbo_size, recovery_dtbo_offset, recovery_acpio_size and recovery_acpio_offset fields.

    • A/B devices use an update and recovery scheme, so there is no need to specify a DTBO or ACPIO recovery image.

    • If a non-A/B device requires a specified recovery image (DTBO or ACPIO), boot image header version 1 or 2 should be used.

  • Device tree blob (DTB). The DTB is stored in the vendor boot partition, so dtb_size and  are no longer shown in the boot image header. dtb_addr field (but will be shown in the vendor boot image header file).

Devices can meet the requirements of the Generic Kernel Image (GKI) architecture, which unifies the core kernel, by using boot image header version 3 , and move the vendor modules required for booting to the vendor_boot partition (this means that the boot image only contains GKI components). If the device:

  • Using GKI (requires android-4.19 or android-5.4 kernel) but not using the A/B update mechanism, you can specify a recovery image using boot image version 3 (for boot images) and boot image version 2 (for recovery images).

  • Without using either GKI or the A/B update mechanism, you can use boot image version 1 to specify the recovery image or use boot image version 2 for both the boot image and the recovery image.

Boot image header version 3 has the following format.

struct boot_img_hdr
{
#define BOOT_MAGIC_SIZE 8
    uint8_t magic[BOOT_MAGIC_SIZE];

    uint32_t kernel_size;    /* size in bytes */
    uint32_t ramdisk_size;   /* size in bytes */

    uint32_t os_version;

    uint32_t header_size;    /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint32_t header_version; /* offset remains constant for version check */

#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
    uint8_t cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
};

Boot image header version 2

Android 10 has updated the boot image header file to version 2, and added the DTB recovery image information section (image size and actual load address).

Boot image header version 2 has the following format.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;               /* size in bytes */
    uint32_t kernel_addr;               /* physical load addr */

    uint32_t ramdisk_size;              /* size in bytes */
    uint32_t ramdisk_addr;              /* physical load addr */

    uint32_t second_size;               /* size in bytes */
    uint32_t second_addr;               /* physical load addr */

    uint32_t tags_addr;                 /* physical addr for kernel tags */
    uint32_t page_size;                 /* flash page size we assume */
    uint32_t header_version;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];       /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                     /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
    uint32_t recovery_[dtbo|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_offset;  /* offset in boot image */
    uint32_t header_size;               /* size of boot image header in bytes */
    uint32_t dtb_size;                  /* size of dtb image */
    uint64_t dtb_addr;                  /* physical load address */
};

Boot image header version 1

Android 9 will convert the unused field of the boot image header file into a header file version field. Devices running Android 9 must use boot image headers with header version 1 or higher (verified by VTS).

Boot image header version 1 has the following format.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;               /* size in bytes */
    uint32_t kernel_addr;               /* physical load addr */
    uint32_t ramdisk_size;              /* size in bytes */
    uint32_t ramdisk_addr;              /* physical load addr */

    uint32_t second_size;               /* size in bytes */
    uint32_t second_addr;               /* physical load addr */

    uint32_t tags_addr;                 /* physical addr for kernel tags */
    uint32_t page_size;                 /* flash page size we assume */
    uint32_t header_version;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];       /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                     /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
    uint32_t recovery_[dtbo|acpio]_size;    /* size of recovery image */
    uint64_t recovery_[dtbo|acpio]_offset;  /* offset in boot image */
    uint32_t header_size;               /* size of boot image header in bytes */
};

Non-A/B devices can specify a DTB/ACPI overlay recovery image to reduce the number of over-the-air (OTA) update failures. (A/B devices do not suffer from this problem and do not need to specify an overlay image.) You can specify a DTBO image or an ACPIO image, but not both (because of the different architectures for which they apply). To correctly configure the boot image header:

  • When using DTBO to restore the image, please add the recovery_dtbo_size and recovery_dtbo_offset fields (do not add the recovery_acpio_size and  recovery_acpio_offset field).

  • When using ACPIO to restore the image, please add the recovery_acpio_size and recovery_acpio_offset fields (do not add recovery_dtbo_size and  recovery_dtbo_offset field).

header_size The field contains the boot image header file size. If the boot image header file version is 1, then in addition to kernel, ramdisk and second sections ,  portion of the boot image. For more information on the  and  fields, see Restore Image. idrecovery_[dtbo|acpio]recovery_[dtbo|acpio]_sizerecovery_[dtbo|acpio]_offset

Legacy boot image header version 0

If a device ships with a version prior to Android 9 and uses an older boot image header, it is considered to be using boot image header version 0.

struct boot_img_hdr
{
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;                /* size in bytes */
    uint32_t kernel_addr;                /* physical load addr */

    uint32_t ramdisk_size;               /* size in bytes */
    uint32_t ramdisk_addr;               /* physical load addr */

    uint32_t second_size;                /* size in bytes */
    uint32_t second_addr;                /* physical load addr */

    uint32_t tags_addr;                  /* physical addr for kernel tags */
    uint32_t page_size;                  /* flash page size we assume */
    uint32_t unused;
    uint32_t os_version;
    uint8_t name[BOOT_NAME_SIZE];        /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE];
    uint32_t id[8];                      /* timestamp / checksum / sha1 / etc */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
};

Implementing Bootconfig in Android 12

In Android 12, the bootconfig feature replaces theandroidboot.*kernel command line options used in Android 11 and earlier. The bootconfig feature is a mechanism to pass configuration details from the build and bootloader to Android 12.

This feature provides a way to separate Android userspace configuration parameters from kernel configuration parameters. Moving lengthyandroidboot.*kernel parameters into the bootconfig file creates space on the kernel cmdline and makes it available for future extensions.

Both the kernel and Android userspace must supportbootconfig .

  • First version with this support: Android 12
  • First kernel version with this support: 12-5.4.xx kernel

Implement bootconfig functionality fornew devices booted with 12-5.10.xx kernel version. If you are upgrading your device, you don't need to implement it.

Examples and sources

As you review the examples and source code in this section, note that the bootconfigcode is formatted slightly differently than the kernel cmdline used in Android 11 and earlier. However, the following distinctions are important for your use:

  • Arguments must be separated by newline escape sequences\n, not spaces.

Bootloader example

For a bootloader example, see the Cuttlefish U-boot reference bootloader implementation. Two commits in the reference are listed below. The first one will upgrade the boot header version support to the latest version. In the example, the first commit updates (or upgrades) version support to the next version, v4. The second one does two things; it adds bootconfig handling, and demonstrates adding parameters at runtime:

Build example

For a build example showingmkbootimg changes to buildvendor_boot.img with vendor bootstrap header v4, see mkbootimg changes for bootconfig . See Cuttlefish changes to do the following:

implement

Partners must add support for their bootloaders and move their build-timeandroidboot.* parameters from the kernel cmdline to the bootconfig file. The best way to implement this change is to do it incrementally; see the Incremental Implementation and Validation section for information on following an incremental process.

If you have searched the /proc/cmdline file for changes to androidboot.* parameters, point them to the /proc/bootconfig file. The ro.boot.*properties are set with the new bootconfig values, so you don't need to make changes to your code using these properties.

Build changes

First, upgrade your boot header version to version 4:

- BOARD_BOOT_HEADER_VERSION := 3

+ BOARD_BOOT_HEADER_VERSION := 4

Addbootconfigkernel command line parameters. This makes the kernel look for the bootconfig section:

BOARD_KERNEL_CMDLINE += bootconfig

bootconfig parameters are created from parameters in BOARD_BOOTCONFIG variables, just like the kernel cmdline is created from BOARD\_KERNEL\_CMDLINE.

Anyandroidboot.* parameter can be moved as is, similar to the following:

- BOARD_KERNEL_CMDLINE += androidboot..selinux=enforcing

+ BOARD_BOOTCONFIG += androidboot..selinux=enforcing

Bootloader changes

The bootloader setsinitramfs before jumping to the kernel. Kernel Boot Configuration Search for the bootconfig section and look for it to be located initramfs, along with the expected trailer.

The boot loader obtainsvendor_boot.imglayout information from the vendor boot image header.

Diagram of bootconfig memory allocation layout

Figure 1. Android 12 bootconfig memory allocation

The bootloader creates the bootconfig section in memory. The bootconfig section contains memory allocations for:

  • parameter
  • 4 B sizeparameters size
  • 4B sizeparameters checksum
  • 12 B bootconfig magic string ( #BOOTCONFIG\n )

Parameters come from two sources: parameters known at build time and parameters unknown at build time. Unknown parameters must be added.

Parameters known at build time are packed into the bootconfig sectionvendor_bootat the end of the image. The size of this section (in bytes) is stored in the vendor bootstrap header fieldvendor_bootconfig_size.

Parameters that are not known at build time are only known at runtime of the bootloader. These must be added to the end of the bootconfig parameters section before applying the bootconfig trailer.

If you need to add any parameters after applying the bootconfig trailer, overwrite the trailer and reapply it.

Incremental implementation and validation

Follow the procedure given in this section to implement the bootconfig functionality step by step. When adding bootconfig parameters, keep the kernel cmdline parameters unchanged.

Important:If the bootconfig function fails to load andandroidboot.*the parameters are not in the kernel cmdline, the device may not boot. Many of these parameters are very important for Android startup. Therefore, Googlerecommends that you implement this feature incrementally to ensure that bootloader and build changes are valid before removing the kernel cmdline parameters.

These are the steps for incremental implementation with validation:

  1. Make bootloader and buildchanges and then do the following:
    1. Add new bootconfig parameters usingBOARD_BOOTCONFIG variables.
    2. Leave the kernel cmdline parameters as is so that the device can continue to boot correctly. This makes debugging and verification easier.
  2. Verifyyour work by inspecting/proc/bootconfig its content. Verify that you see the newly added parameters after the device boots.
  3. Movedparameters from kernel cmdline to bootconfig usingBOARD_BOOTCONFIGvariables and bootloader. androidboot.*
  4. Verifythat each parameter exists/proc/bootconfig and that theyare not/proc/cmdlineMedium. If you can verify this, your implementation is successful.

Precautions for OTA upgrade and downgrade

You should be particularly careful when managing OTA upgrades and downgrades between different versions of Android or different kernel versions.

Android 12 is the first version to support bootconfig. If you downgrade to any previous version, you must use kernel command line parameters instead of bootconfig.

bootconfig is supported in kernel version 12-5.4 and higher. If downgrading to any previous version (including 11-5.4), kernel command line parameters must be used.

Upgrading from Android 11 and earlier to Android 12 and later can continue to use kernel cmdline parameters. The same goes for upgrading the kernel version.

troubleshooting

When performing theverification step, if you don't see the expected parameters in/proc/bootconfig, please check< Kernel log in /span>logcat. If the kernel supports it, there is always a log entry in bootconfig.

Sample log output

$ adb logcat | grep bootconfig
02-24 17:00:07.610     0     0 I Load bootconfig: 128 bytes 9 nodes

If you see an error log returned, there is a problem loading bootconfig. To see the different error types, look at init/main.c .

DTB image

Android implementations can include device tree blob (DTB) images for use by the bootloader. The location of the DTB image (and the options for specifying DTB image parameters) vary between Android versions.

  • In Android 11, devices usingGeneric Kernel Image (GKI) must support the vendor Boot partition, which includes all vendor-specific information relocated from the boot partition. Because the DTB image contains vendor-specific data, it is now part of the vendor boot partition. To specify DTB image parameters, see Vendor Boot Header.

  • In Android 10, devices can include DTB images in the boot partition. To specify DTB image parameters, seeIncluding a DTB image in a boot image.

  • In Android 9 and lower, the DTB image can exist in its own partition, or it can be attached to the kernelimage.gz to create a kernel + DTB image (which is then passed to mkbootimg to create boot.img ).

DTB image format

In Android 10 and higher, DTB images must use one of the following formats:

  • DT blobs are concatenated one after another. The bootloader uses the totalsize fields in each FDT header to read and parse the corresponding blob.

  • DTB/DTBO partition. The bootloader checks the dt_table_entry structure (containing id , rev and custom fields) there is an efficient way to select the correct DT blob. For more information, seeDTB/DTBO Partitions.

Include DTB image in boot image

Devices running Android 10 can include DTB images in the boot image. This eliminates the need for Android support to attach DTB images to scripts in the kernel and allows the use of Vendor Test Suites (VTS) Test to verify (and standardize) DTB placement. image.gz

Additionally, for non-A/B devices, it is safer to have the DTB as part of the recovery image rather than in a separate partition to prevent issues caused by OTA outages. During OTA, if a problem occurs after the DTB partition is updated (but before the full update is completed), the device will attempt to boot into recovery mode to complete the OTA; however, since the DTB partition has been updated, the recovery image (which has not yet been updated) may appear Mismatch. Having the DTB image as part of the boot image format prevents such problems by making the recovery image self-sufficient (i.e., it does not depend on another partition).

boot image structure

Devices running Android 10 can include DTB images using the following boot image structure.

Boot image section Number of pages
Boot title (1 page) 1
Kernel (l page) l = ( kernel_size + page_size - 1) / page_size
Ramdisk (m pages) m = ( ramdisk_size + page_size - 1) / page_size
Second stage bootloader (n pages) n = ( second_size + page_size - 1) / page_size
Restoring DTBO (page o) o = ( recovery_dtbo_size + page_size - 1) / page_size
DTB (page p) p = ( dtb_size + page_size - 1) / page_size

DTB image path

For devices running Android 10, you can use the mkbootimg.py tool and the following parameters to specify the path to the DTB image.

debate describe
dtb Path to the DTB image to include in the boot/recovery image.
dtb_offset When is added to the base parameter, provides the physical load address of the final device tree. For example, if the base parameter is 0x10000000 and the dtb_offset parameter is 0x01000000 , then the boot image header The dtb_addr_field is filled with 0x11000000 .

Board configuration variablesBOARD_PREBUILT_DTBIMAGE_DIR must be used to specify the path to the DTB image. If multiple files with extension exist in the directory BOARD_PREBUILT_DTBIMAGE_DIR, the Android build system concatenates these files to create the final DTB image used to create the boot image. *.dtb

To pass parameters to  using the DTB image in the directory specified by BOARD_PREBUILT_DTBIMAGE_DIR, the board must be configured The variable is set to  . For example:dtbmkbootimg.pyBOARD_INCLUDE_DTB_IN_BOOTIMGtrue

BOARD_INCLUDE_DTB_IN_BOOTIMG := true

You can appenddtb_offset parameters toBOARD_MKBOOTIMG_ARGSboard configuration variables as well as other offset and header versions. For example:

BOARD_MKBOOTIMG_ARGS := --ramdisk_offset $(BOARD_RAMDISK_OFFSET) --dtb_offset $(BOARD_DTB_OFFSET) --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) --header_version $(BOARD_BOOTIMG_HEADER_VERSION)

Bootloader support

For VTS to run successfully on devices running Android 10, the bootloader must support the newer boot image and the kernel command line argument must be addedandroidboot.dtb_idx to indicate the selected device tree (DT) index. You may only specify one (1) index. For example, parameter androidboot.dtb_idx=N will N report the device tree selected by the boot loader from the set of DTBs present in the boot image. Zero-based index.

Lock/unlock bootloader

By default, most Android devices ship with a locked bootloader, which means users cannot flash the bootloader or device partition. If desired, you (and device users with developer options enabled) can unlock the bootloader to flash a new image.

Unlock the bootloader

To unlock the bootloader and enable the partition to be flashed, run thefastboot flashing unlock command on the device. Once set, unlocked mode persists across reboots.

The device should reject the command unlessget_unlock_ability is set to 1 . If set to  , the user needs to boot to the home screen, open the Settings> System> Developer Options menu and Enable the OEM unlocking option (set to  ). Once set, this mode persists across reboots and factory resets. fastboot flashing unlock0get_unlock_ability1

When sending the fastboot flashing unlock command, the device should prompt the user to warn them that they may encounter problems with unofficial images. After the user acknowledges the warning, the device should perform a factory data reset to prevent unauthorized data access. The bootloader should reset the device even if it fails to reformat properly. The persistent flag can only be set after a reset so the device can be reflashed.

Any RAM that has not been overwritten should be reset during fastbootfastboot flashing unlock. This measure prevents attacks that read the remaining RAM contents from the last boot. Likewise, unlocked devices should clear RAM on every boot (unless this creates unacceptable latency), but should be reserved for kernel ramoops Area.

Lock bootloader

To lock the bootloader and reset the device, run thefastboot flashing lock command on the device. Devices intended for retail should be shipped locked ( get_unlock_abilityBack0 ) to ensure that attackers cannot compromise the device by installing a new system or boot image.

Set lock/unlock properties

ro.oem_unlock_supportedProperty should be set at build time based on whether the device supports flash to unlock.

  • If the device supports flashing and unlocking, set ro.oem_unlock_supported to 1 .
  • If the device does not support flashing and unlocking, set ro.oem_unlock_supported to 0 .

If the device supports flash unlocking, the bootloader should set the kernel command line variable androidboot.flash.locked to 1 if locked or to < /span>0 (if unlocked) to indicate locked status. This variable must be set in bootconfig, not the kernel command line in Android 12.

For devices that support dm-verity, use ro.boot.verifiedbootstate to ro.boot.flash.locked is set to 0 ; this will unlock the bootloader if the verified boot status is orange.

Protect critical parts

Devices should support locking and unlocking of critical sections, which are defined as anything required to boot the device into the bootloader. These parts may include fuses, virtual partitions for sensor hubs, first-stage bootloaders, etc. To lock down critical sections, you must use a mechanism to prevent code running on the device (kernel, recovery image, OTA code, etc.) from intentionally modifying any critical section. If the device is in a locked critical state, OTA should be unable to update the critical section.

Transitioning from locked to unlocked state should require physical interaction with the device. This interaction is similar to the effect of a runfastboot flashing unlock command, but requires the user to press a physical button on the device. The device should not allow programmatic transitions from the lock critical state to the unlock criticalcritical state without physical interaction, and the device should not unlock criticalStatus Shipping.

Guess you like

Origin blog.csdn.net/yangzex/article/details/132968023