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. boot
recovery
Bootloader flow example
Here is an example of the bootloader flow:
-
Load and initialize memory.
-
Verify the device according tothe boot-time verification process.
-
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
-
If using A/B update, determines the current slot to start.
-
Determines whether recovery mode should be initiated. For more information, seeSupporting OTA updates.
-
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.-
Loads the kernel into memory as a self-executable compressed binary. The kernel decompresses itself and begins executing into memory.
-
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
totrue
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
:fromCONFIG_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.
- Provide
- 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 asbootstat
andinit
) 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_prop
bootloader_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 moredetail
.- 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 causingsubreason
. You can specify multipledetail
values, which should generally be ordered by importance. However, it is possible to report multipledetail
values of equal importance.
- Required
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, andramoops
should retain persistent content."warm"
: Typically indicates that memory and devices remain in some state, andramoops
(see thepstore
driver in the kernel) the backing store contains persistence content."shutdown"
"reboot"
: Usually meansramoops
status and hardware status are unknown. This value is the same generic value ascold
,hard
andwarm
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). kBootReasonMap
kBootReasonMap
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"
becausebootstat
may be able to checkkernel_panic signatures
oframoops
in order to optimize the sub-cause to canonicalsystem_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 optimizereason
.
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 inkBootReasonMap
. - Consider what
"bark"
means to someone unfamiliar with the technology, and determine whether there is asubreason
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:
|
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:
|
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:
|
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
andsecond_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
andrecovery_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
andrecovery_dtbo_offset
fields (do not add therecovery_acpio_size
andrecovery_acpio_offset
field). -
When using ACPIO to restore the image, please add the
recovery_acpio_size
andrecovery_acpio_offset
fields (do not addrecovery_dtbo_size
andrecovery_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. id
recovery_[dtbo|acpio]
recovery_[dtbo|acpio]_size
recovery_[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 bootconfig
code 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:
- Use (or upgrade to)vendor boot header version v4 .
- 将bootconfig to the kernel cmdline and move selected parameters to bootconfig 。
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
Addbootconfig
kernel 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.img
layout information from the vendor boot image header.
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 size
parameters size
- 4B size
parameters 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_boot
at 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:
- Make bootloader and buildchanges and then do the following:
- Add new bootconfig parameters using
BOARD_BOOTCONFIG
variables. - Leave the kernel cmdline parameters as is so that the device can continue to boot correctly. This makes debugging and verification easier.
- Add new bootconfig parameters using
- Verifyyour work by inspecting
/proc/bootconfig
its content. Verify that you see the newly added parameters after the device boots. - Movedparameters from kernel cmdline to bootconfig using
BOARD_BOOTCONFIG
variables and bootloader.androidboot.*
- Verifythat each parameter exists
/proc/bootconfig
and that theyare not/proc/cmdline
Medium. 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 kernel
image.gz
to create a kernel + DTB image (which is then passed tomkbootimg
to createboot.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 (containingid
,rev
andcustom
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:dtb
mkbootimg.py
BOARD_INCLUDE_DTB_IN_BOOTIMG
true
BOARD_INCLUDE_DTB_IN_BOOTIMG := true
You can appenddtb_offset
parameters toBOARD_MKBOOTIMG_ARGS
board 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 unlock
0
get_unlock_ability
1
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_ability
Back0
) to ensure that attackers cannot compromise the device by installing a new system or boot image.
Set lock/unlock properties
ro.oem_unlock_supported
Property 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
to1
. - If the device does not support flashing and unlocking, set
ro.oem_unlock_supported
to0
.
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 critical
critical state without physical interaction, and the device should not unlock critical
Status Shipping.