在 Android 12 中实现 Bootconfig

在 Android 12 中,bootconfig 功能取代了 Android 11 及更低版本中使用的androidboot.*内核命令行选项。 bootconfig 功能是一种将配置详细信息从构建和引导加载程序传递到 Android 12 的机制。

此功能提供了一种将 Android 用户空间的配置参数与内核的配置参数分开的方法。将冗长的androidboot.*内核参数移动到 bootconfig 文件会在内核 cmdline 上创建空间,并使其可用于将来的扩展。

内核和 Android 用户空间都必须支持bootconfig

  • 具有此支持的第一个版本:Android 12
  • 具有此支持的第一个内核版本:12-5.4.xx 内核

为使用 12-5.10.xx 内核版本启动的设备实施 bootconfig 功能。如果您正在升级设备,则无需实施它。

示例和来源

当您查看本节中的示例和源代码时,请注意bootconfig代码的格式与 Android 11 及更低版本中使用的内核 cmdline 的格式略有不同。但是,以下区别对您的使用很重要:

  • 参数必须由换行符转义序列\n分隔,而不是空格。

引导加载程序示例

有关引导加载程序示例,请参阅 Cuttlefish U-boot 参考引导加载程序实现。下面列出了参考中的两个提交。第一个将引导头版本支持升级到最新版本。在示例中,第一次提交更新(或升级)版本支持到下一个版本,v4。第二个做两件事;它添加了 bootconfig 处理,并演示了在运行时添加参数:

构建示例

有关显示mkbootimg更改以使用供应商引导标头 v4 构建vendor_boot.img的构建示例,请参阅mkbootimg changes for bootconfig 。请参阅 Cuttlefish 更改以执行以下操作:

执行

合作伙伴必须为其引导加载程序添加支持,并将其构建时androidboot.*参数从内核 cmdline 移至 bootconfig 文件。实施此更改的最佳方法是逐步进行;有关遵循增量过程的信息,请参阅增量实施和验证部分。

如果您有在 /proc/cmdline 文件中搜索androidboot.*参数的更改,请将它们指向 /proc/bootconfig 文件。 ro.boot.*属性使用新的bootconfig值设置,因此您无需使用这些属性对代码进行更改。

构建更改

首先,将您的引导头版本升级到版本 4:

- BOARD_BOOT_HEADER_VERSION := 3

+ BOARD_BOOT_HEADER_VERSION := 4

添加bootconfig内核命令行参数。这使得内核寻找 bootconfig 部分:

BOARD_KERNEL_CMDLINE += bootconfig

bootconfig 参数是从BOARD_BOOTCONFIG变量中的参数创建的,很像内核 cmdline 是从BOARD\_KERNEL\_CMDLINE创建的。

任何androidboot.*参数都可以按原样移动,类似于以下内容:

- BOARD_KERNEL_CMDLINE += androidboot..selinux=enforcing

+ BOARD_BOOTCONFIG += androidboot..selinux=enforcing

引导加载程序更改

引导加载程序在跳转到内核之前设置initramfs内核引导配置搜索 bootconfig 部分,并寻找它位于initramfs,以及预期的预告片。

引导加载程序从供应商引导映像头中获取vendor_boot.img布局信息。

Diagram of bootconfig memory allocation layout

图 1. Android 12 bootconfig 内存分配

引导加载程序在内存中创建 bootconfig 部分。 bootconfig 部分包含以下内容的内存分配:

  • 参数
  • 4 B尺寸parameters size
  • 4 B大小parameters checksum
  • 12 B bootconfig 魔法字符串 ( #BOOTCONFIG\n )

参数来自两个来源:构建时已知的参数和构建时未知的参数。必须添加未知参数。

构建时已知的参数被打包到 bootconfig 部分中vendor_boot映像的末尾。该部分的大小(以字节为单位)存储在供应商引导标头字段vendor_bootconfig_size中。

在构建时不知道的参数仅在引导加载程序的运行时才知道。在应用 bootconfig 预告片之前,这些必须添加到 bootconfig 参数部分的末尾。

如果在应用 bootconfig 预告片后需要添加任何参数,请覆盖预告片并重新应用它。

增量实施和验证

按照本节中给出的过程逐步实施 bootconfig 功能。在添加 bootconfig 参数时,保持内核 cmdline 参数不变。

这些是带有验证的增量实施的步骤:

  1. 进行引导加载程序和构建更改,然后执行以下操作:
    1. 使用BOARD_BOOTCONFIG变量添加新的 bootconfig 参数。
    2. 保持内核 cmdline 参数原样,以便设备可以继续正确启动。这使得调试和验证更加容易。
  2. 通过检查/proc/bootconfig的内容来验证您的工作。验证您是否在设备启动后看到了新添加的参数。
  3. 使用BOARD_BOOTCONFIG变量和引导加载程序androidboot.*参数从内核 cmdline 移动到 bootconfig。
  4. 验证每个参数是否存在于/proc/bootconfig中并且它们不在/proc/cmdline中。如果您可以验证这一点,那么您的实施是成功的。

OTA升级降级注意事项

当您管理不同版本的 Android 或不同内核版本之间的 OTA 升级和降级时,应特别小心。

Android 12 是第一个支持 bootconfig 的版本。如果降级到之前的任何版本,必须使用内核命令行参数而不是 bootconfig。

内核版本 12-5.4 及更高版本支持 bootconfig。如果降级到之前的任何版本(包括 11-5.4),必须使用内核命令行参数。

从 Android 11 及更早版本升级到 Android 12 及更高版本可以继续使用内核 cmdline 参数。升级内核版本也是如此。

故障排除

执行验证步骤时,如果在/proc/bootconfig中没有看到预期的参数,请检查logcat中的内核日志。如果内核支持,则 bootconfig 始终存在一个日志条目。

示例日志输出

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

如果您看到返回的错误日志,则说明加载 bootconfig 时出现问题。要查看不同的错误类型,请查看init/main.c