Implement bootconfig in Android 12

In Android 12, the bootconfig feature replaces the androidboot.* kernel cmdline options in use with Android 11 and lower. The bootconfig feature is a mechanism for passing configuration details from the build and bootloader to Android 12.

This feature provides a way to separate the configuration parameters for Android user-space from those for the kernel. Moving the lengthy androidboot.* kernel parameters to the bootconfig file creates space on the kernel cmdline and makes it available for future expansion.

Both the kernel and the Android user-space must support bootconfig.

  • First release that has this support: Android 12
  • First kernel version that has this support: 12-5.4.xx kernel

Implement the bootconfig feature for new devices launching with a 12-5.10.xx kernel version. You don't need to implement it if you're upgrading devices.

Examples and source

As you view the examples and source code in this section, note that the format of the bootconfig code is only slightly different from the format of the kernel cmdline used in Android 11 and lower. However, the following difference is important for your usage:

  • Parameters must be separated by the newline escape sequence \n, not by 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 uprevs the boot header version support to the latest version. In the example, the first commit updates (or uprevs)the version support to the next one, v4. The second does two things; it adds bootconfig handling, and demonstrates adding parameters at runtime:

Build example

For a build example that shows mkbootimg changes to build the vendor_boot.img with vendor boot header v4, see mkbootimg changes for bootconfig. See the Cuttlefish changes to do the following:

Implementation

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

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

Build changes

First, uprev your boot header version to version 4:

- BOARD_BOOT_HEADER_VERSION := 3

+ BOARD_BOOT_HEADER_VERSION := 4

Add the bootconfig kernel cmdline parameter. This makes the kernel look for the bootconfig section:

BOARD_KERNEL_CMDLINE += bootconfig

The bootconfig parameters are created from the parameters in the BOARD_BOOTCONFIG variable, much like the kernel cmdline is created from BOARD\_KERNEL\_CMDLINE.

Any androidboot.* parameters can be moved as-is, similar to the following:

- BOARD_KERNEL_CMDLINE += androidboot..selinux=enforcing

+ BOARD_BOOTCONFIG += androidboot..selinux=enforcing

Bootloader changes

The bootloader sets up the initramfs before jumping to the kernel. The kernel boot configuration searches for the bootconfig section, and looks for it to be at the very end of initramfs, with the expected trailer.

The bootloader gets the vendor_boot.img layout 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 the following:

  • Parameters
  • 4 B size parameters size
  • 4 B size parameters checksum
  • 12 B bootconfig magic string (#BOOTCONFIG\n)

The parameters come from two sources: Parameters known at build time, and parameters that aren't known at build time. Unknown parameters must be added.

Parameters known at build time are packaged into the end of the vendor_boot image in the bootconfig section. The size of the section is stored (as bytes) in the vendor boot header field vendor_bootconfig_size.

The parameters that aren't known at build time are only known at runtime in the bootloader. These must be added to the end of the bootconfig parameters section before the bootconfig trailer is applied.

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

Incremental implementation and validation

Implement the bootconfig feature incrementally by following the process given in this section. Leave the kernel cmdline parameters untouched while the bootconfig parameters are added.

These are the steps for an incremental implementation, with validation:

  1. Make the bootloader and build changes, then do the following:
    1. Use the BOARD_BOOTCONFIG variable to add a new bootconfig parameter.
    2. Keep the kernel cmdline parameters the way they are, so that the device can continue to boot correctly. This makes debugging and validation much easier.
  2. Verify your work by checking the contents of /proc/bootconfig. Verify that you see the newly added parameter after the device has booted.
  3. Move the androidboot.* parameters from the kernel cmdline to bootconfig, using the BOARD_BOOTCONFIG variable and the bootloader.
  4. Verify that each of the parameters exists in /proc/bootconfig AND that they aren't in /proc/cmdline. If you can verify this, your implementation was successful.

OTA upgrading and downgrading considerations

When you're managing OTA upgrades and downgrades between different versions of Android, or different kernel versions, special care should be taken.

Android 12 is the first version with bootconfig support. If downgrading to any version before that, kernel cmdline parameters must be used instead of bootconfig.

Kernel versions 12-5.4 and later support bootconfig. If downgrading to any version before that(including 11-5.4), kernel cmdline parameters must be used.

Upgrades from Android 11 and lower to Android 12 and higher can keep using kernel cmdline parameters. The same goes for upgrading kernel versions.

Troubleshooting

When you perform the verify step, if you don't see the expected parameters in /proc/bootconfig, check the kernel logs in logcat. There's always a log entry present for bootconfig if the kernel supports it.

Example 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, then there was a problem loading the bootconfig. To see different error types, view init/main.c.