Skip to main content

概述

本页是一份实践演练,介绍如何从 U-Boot 控制台执行多镜像 UEFI 胶囊更新。 它是对本章中胶囊概念页面的补充,展示了以下操作的具体命令:
  1. 查询开发板可以更新哪些固件镜像。
  2. 构建 mkeficapsule 主机工具。
  3. 将多个固件负载(U-Boot、TZ、XBL 等)打包成单个 UEFI 胶囊(可签名或不签名)。
  4. 将胶囊放置到 EFI 系统分区(ESP)上,通过设置 OsIndications 触发更新, 然后重启以应用更新。
  5. 验证结果。

支持的 SoC

以下 SoC 的流程完全相同,只有 defconfig 不同。

查询支持的镜像

刷写 U-Boot,停在 U-Boot 控制台,然后运行:
此命令会遍历每个固件管理协议(Firmware Management Protocol,FMP)实例,并为 开发板暴露的每个可更新镜像打印一行:
该列表因开发板而异(根据该开发板的 GPT 构建),因此并非每块开发板都会显示所有 组件。只有出现在此列表中的镜像才能在该开发板上通过胶囊更新。 请记下此命令为每个组件报告的 image-guid 和 image-index 值——它们会在后续 章节的胶囊配置中使用。image-guid 决定应用更新时的目标分区。

构建 mkeficapsule 工具

首先,获取源码:
然后将主机工具构建到 .output 文件夹中:
生成的二进制文件位于 .output/tools/mkeficapsule。下文所有命令均通过路径调用它。

设置胶囊文件夹

为开发板创建一个具有以下结构的工作文件夹:
只包含需要更新的镜像的负载。每个负载都必须出现在 efidebug capsule images 的 输出中。

胶囊配置文件格式

配置由一系列 { … } 块组成,每个块是一组 key: value 键值对。一个块描述一个 负载。 分组规则:共享同一 capsule: 文件名的负载会被打包成一个多镜像胶囊。不同的 文件名会生成不同的胶囊。 test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt 中提供了一份可作为模板 的现成示例配置。

未签名的多镜像胶囊

以下示例使用 efidebug capsule images 报告的值。image-guid 决定目标分区; 请将每个 image-index 设置为该命令为对应组件报告的值:
三个块都使用 capsule: Unsigned.cap,因此该工具会把三个负载都打包到这一个 文件中。

签名的多镜像胶囊

首先,使用 OpenSSL 生成签名密钥和自签名公共证书。私钥用于签署每个负载;证书会 嵌入 U-Boot 镜像中(请参阅为签名胶囊启用身份验证), 并在开发板上用于验证签名:
然后向每个块添加 private-key: / pub-key-cert:(以及 monotonic-count:), 指向上面生成的密钥和证书:
在开发板上验证签名胶囊,还要求 U-Boot 镜像在构建时启用了胶囊身份验证并包含匹配 的公共证书。请参阅为签名胶囊启用身份验证。

生成胶囊

在开发板文件夹内运行该工具,以便 payload:/capsule: 的相对路径能够正确解析:
对于多镜像配置,输出如下:
通过转储胶囊的头部来验证其结构:
确认 EFI_FMP_HDR.PAYLOAD_ITEM_COUNT 等于负载数量,并且每个 FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID / UPDATE_IMAGE_INDEX 与配置匹配。 对于签名胶囊,每个负载还会额外显示一个 EFI_FIRMWARE_IMAGE_AUTH 块。

为签名胶囊启用身份验证

对于未签名胶囊,请跳过本节。出厂的开发板镜像已启用 EFI_CAPSULE_ON_DISK 和 EFI_CAPSULE_FIRMWARE_RAW,因此可以直接前往 将胶囊放置到 ESP。
签名胶囊要求 U-Boot 镜像启用胶囊身份验证,而该功能默认未启用,因此必须在应用 胶囊之前完成以下操作:
  1. 克隆 qualcomm-linux/u-boot 仓库并切换到 qcom-next(如果 构建 mkeficapsule 工具中的检出已存在,可跳过):
  2. 将生成的公共证书(capsule_pub.crt)复制到 U-Boot 源码树中,然后将胶囊 身份验证选项添加到开发板的 defconfig (configs/<board>_defconfig,例如 configs/qcom_lemans_defconfig),并将 CONFIG_EFI_CAPSULE_CRT_FILE 指向该证书(相对于 U-Boot 源码树的路径):
  3. 构建 U-Boot(请参阅 Qualcomm Linux 上的 U-Boot), 并将生成的镜像刷写到开发板的 uefi 分区。
使用与嵌入证书不匹配的密钥签名的胶囊会在应用时被拒绝。

将胶囊放置到 ESP

将 .cap 文件放到 ESP 上的 \EFI\UpdateCapsule\ 中。使用开发板支持的任意传输 机制将文件复制到该位置——例如,挂载 ESP (mount /dev/disk/by-partlabel/efi /mnt/esp),如果 EFI/UpdateCapsule 目录 不存在则创建它,然后将胶囊复制进去。 只有当 OsIndications 设置了 EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED(0x4)位时, capsule-on-disk 才会运行。U-Boot(lib/efi_loader/efi_capsule.c 中的 check_run_capsules())会在应用后清除该位,因此每次应用前都需要重新设置。 下次启动时,capsule-on-disk 会自动发现 \EFI\UpdateCapsule\*.cap,应用所有 负载,清除该文件,并清除 OsIndications 位——无需任何 U-Boot 控制台命令来 触发它。 胶囊就位后,从内核提示符触发更新并重启:

验证结果

应用更新的那次启动完成后,在 U-Boot 控制台执行:
针对每个已更新的镜像,确认 fw_version 已提升为配置中的 fw-version,并且 last_attempt_status = success。
显示上次应用的每个胶囊的结果码。
再次确认镜像集合,并反映已更新的版本。