Skip to main content
systemd-boot 统一可扩展固件接口(UEFI)启动管理器提供了控制启动流程的选项,并加载用户选择的引导加载程序。配置文件、内核镜像、initrd 镜像和其他 EFI 镜像必须位于 EFI 分区上。 要将 Qualcomm Linux 内核直接作为 EFI 镜像运行,请使用 CONFIG_EFI_STUB 进行构建。systemd-boot 支持两种配置:
  • Type1:Type1 配置使用引导加载程序规范(BLS)描述文件。您可以在 EFI 上的 /loader/entries/ 目录中找到这些文件。
  • Type2:Type2 配置使用统一内核镜像(UKI)。这些镜像将内核、initrd 和内核命令行组合到单个 EFI 可执行文件中。Type2 提供更好的安全性,因为 UKI 包含设备启动所需的全部信息。对 UKI 镜像签名可保护其中包含的所有实体。如果启用了 UEFI 安全启动,系统只会加载已签名的镜像,因此签名成为必需项。
有关更多详细信息,请参阅 systemd-boot 注意 要使用启用了安全启动的设备,必须进行签名。

UKI

UKI 是将 UEFI 启动 stub 程序、Qualcomm Linux 内核镜像、initrd 和其他资源组合到单个 UEFI 可移植可执行(PE)文件中的组合体。UEFI 启动 stub 在 UEFI PE 二进制文件内部查找内核调用所需的各种资源。这允许将各种资源组合到单个 UKI 镜像中,然后可以使用 sbsign 对其进行签名。Qualcomm Linux 使用 sbsign 对 PE 文件签名,而 DTB 等非 PE 文件则使用 OpenSSL 签名。 有关 UKI 的更多详细信息,请参阅 unified_kernel_image。下表显示了 uki.efi 的内容:

镜像 recipe

meta-qcom/recipes-kernel/images 包含以下 recipe:
  • esp-qcom-image.bb 生成 VFAT 镜像 efi.bin,其中包含 uki.efisystemd-boot
meta-qcom/classes-recipe/image_types_qcom.bbclass 类会调用 esp-qcom-image

EFI 镜像

EFI 镜像 efi.bin 是存储在闪存 EFI 分区中的 VFAT 文件系统镜像。此 VFAT 文件系统包含 UEFI 加载并将执行控制权转移给 systemd-boot 所需的镜像。为了将执行控制权转移给 systemd-boot 管理器,UEFI 会挂载 efi.bin,加载 bootaa64.efi 并执行它。systemd-boot 管理器解析 loader.conf,加载内核镜像,并将控制权转移给它。 有关 EFI 结构的更多信息,请参阅 EFI 系统分区 以下是来自 Qualcomm Linux 的 efi.bin 示例结构。它在 /ostree/poky-<sha256-sum> 目录下包含 systemd-boot 的 bootaa64.efi 和 Qualcomm Linux 内核 vmlinuz-<version>
图:生成的带 OSTree 支持的 ``efi.bin`` 文件

图:生成的带 OSTree 支持的 efi.bin 文件

签名

安全启动是 UEFI 标准中的一项功能,但在 Qualcomm Linux 中默认未启用。启用后,安全启动会通过维护一个经过加密签名的二进制文件列表(这些文件在设备启动时经身份验证成功后才会运行),为预启动过程增加一层保护。这可确保设备的启动固件和 Linux 操作系统启动组件(例如启动管理器、内核和 initramfs)未被篡改。 UEFI 安全启动使用数字签名来验证其加载的二进制代码的真实性和完整性。UEFI 安全变量存储所有密钥。实现 UEFI 安全启动涉及使用平台密钥(PK)、密钥交换密钥(KEK)、数据库(DB)和禁用签名数据库(DBX)。 使用安全启动需要 PK、KEK 和 DB 密钥。允许存在多个 KEK、DB 和 DBX,但只允许一个 PK。 启用 UEFI 安全启动需要在系统中注册 PK。Qualcomm 建议在安全启动启用过程的最后一步配置 PK。有关 Qualcomm 如何实现 UEFI 安全启动功能的更多信息,请参阅安全启动

用于为 Qualcomm Linux 构建生成的 Linux OS 镜像签名的主机工具 signing_tool.py

启用 UEFI 安全启动需要对 EFI 和 DTB 镜像签名。使用 signing_tool.py 主机签名工具可简化此过程。此命令行 Python 脚本在 Linux 主机(Ubuntu 20.04 或更高版本)上运行。它通过两次单独的操作自动完成 EFI 和 DTB 镜像的签名。 主机签名工具可在 GitHub 上下载。 主机签名工具在安装了 Python3 的 Linux 计算机上运行。它可以在一次操作中签名 EFI 镜像或 DTB 镜像。要同时签名 EFI 和 DTB 镜像,您必须使用不同的输入调用该工具两次。
图:安装了 OpenSSL 和 sbsign 的 Linux 计算机

图:安装了 OpenSSL 和 sbsign 的 Linux 计算机

主机工具需要未签名的 EFI 或 DTB 文件以及证书和密钥作为输入。调用后,该工具会解包未签名的镜像,使用提供的密钥和证书对可用项进行签名,然后重新打包镜像,用已签名版本替换未签名版本。

前提条件

要运行此工具,请在 Linux 主机上安装以下内容:
  • OpenSSL、sbsign 和 mtools 实用程序
  • Python3
  • pip、subprocess、shlex、socket、glob 和 shutil Python 模块

配置主机签名工具

在开始操作之前,您必须先配置主机签名工具。 主机工具要求在 config.ini 配置文件中提供必要的信息。该工具读取此文件并相应地对镜像进行签名。以下代码片段显示了配置文件中的变量:

config.ini 文件

表:config.ini 文件中的变量 要使用 config.ini 文件配置主机签名工具,请执行以下操作:
  1. 设置 operation 变量以指定要执行的操作。选项为 sign_image
  2. 如果选择 operation == sign_image,请通过设置 image_type 变量指定要签名的镜像。选项为 efidtb
  3. 使用 file_path 变量指明未签名的 EFI 和 DTB 镜像、密钥和证书的位置。
    • 如果在配置文件中选择 local,请手动将 EFI 和 DTB 镜像、密钥和证书文件复制到本地工作目录:
      1. 在与脚本相同的路径下创建 unsigned_binaries 目录,然后将 efi.bindtb.bin 镜像复制到该目录中。
      2. 在与脚本相同的路径下创建 keys 目录,然后将 db.authdb.crtdb.keyKEK.authPK.auth 文件复制到该目录中。
    • 如果希望脚本自动从同一网络中的远程 Linux 计算机复制所需文件,请在配置文件中选择 remote。在配置文件中,为以下变量提供信息:
      • local_machine_private_key_path(必填)
      • [efi_config] 部分(如果 operationsign_imageimage_typeefi
      • [keys_config] 部分(如果 operationsign_image
      • [dtb_config] 部分(如果 operationsign_imageimage_typedtb注意 该脚本支持在同一网络内通过 SCP 从另一台 Linux 计算机复制文件。
  4. 当配置文件中的 image_type 设置为 efi 时,请更新 loader_conf_timeout 变量。
  5. 如果遗漏了任何配置信息,脚本在运行时会通过命令行提示您输入缺失的详细信息。

运行主机签名工具

  1. 完成代码构建过程并获得未签名的 efi.bindtb.bin 镜像后,运行主机签名工具。
  2. 将主机签名工具文件(signing_tool.pyconfig.ini)存储在 Linux 计算机上。确保这两个文件位于同一工作目录中。
  3. 按照配置说明设置主机签名工具。
  4. 运行以下命令从命令行启动主机工具:$python3 signing_tool.py。主机签名工具会在屏幕上显示您的选择和操作命令。它还会在命令行中显示错误。工具完成处理后,会在同一工作目录中创建一个名为 signed_binaries 的目录。已签名的 efi.bindtb.bin 镜像存储在该目录中。签名完成后,该工具会删除其他用户创建的目录。
  5. 请执行此过程两次,一次针对 efi.bin,一次针对 dtb.bin。每次签名操作后,在开始新操作之前,请删除 signed_binaries 目录。

主机签名工具工作流程

下图显示了主机签名工具的工作流程:
图:主机签名工具工作流程

图:主机签名工具工作流程

  • 主机工具需要 efi.bindtb.bin 的路径(绝对路径或网络路径)。
    • 带 OSTree 支持的 efi.bin 包含 vmlinuz-x.y.z(Qualcomm Linux 内核镜像)和 bootaa64.efi(引导加载程序镜像)。
    • dtb.bin 包含 qclinux_fit.img
  • 主机工具需要 certificatekey 的路径(绝对路径或网络路径)来对镜像签名。
  • 主机工具将 efi.bindtb.bin 挂载到 FAT 分区上,其目录结构如下所示,并各自遵循单独的签名流程:efi.bin 的目录结构:
    图:efi.bin

    图:efi.bin

    图:efi.bin 带 OSTree 支持的 efi.bin 的目录结构:
    图:带 OSTree 支持的 efi.bin

    图:带 OSTree 支持的 efi.bin

    图:带 OSTree 支持的 efi.bin dtb.bin 的目录结构:
    图:dtb.bin

    图:dtb.bin

  • 对镜像签名后,主机工具会将 .auth 文件复制到 efi.bindtb.bin/loader/keys/authkeys 目录中。
  • 主机工具在 systemd-boot 加载程序配置中配置等待时间。此等待时间会暂停内核加载,让您可以查看并选择 systemd-boot 菜单选项。loader.conf 文件必须存在于更新后的 efi.bin 文件中。注意 此签名过程不适用于 dtb.bin 文件。
    • 主机工具会配置 /loader/loader.conf
    • loader.conf 的语法为 timeout x,其中 x = 超时时间(秒)。
  • 镜像签名后,主机工具会将 efi.bin/dtb.bin 从 FAT 分区卸载。将已签名的 efi.bindtb.bin 存储在主机上与主机工具类似的路径下的 signed_binaries 目录中。
  • 以下是已签名的 efi.bindtb.bin 的目录结构:
    图:efi.bin 和 dtb.bin 文件的目录结构

    图:efi.bin 和 dtb.bin 文件的目录结构

efi.bin 签名流程

  • 主机工具使用 sbsign 实用程序分别对 uki.efi 或 vmlinuz.x.y.z 和 bootaa64.efi 镜像进行签名。
  • sbsign 的签名过程需要 certificatekey。请核对以下语法,其中 dsk1.key 为密钥,dsk1.crt 为证书,输出文件名与输入文件相同:
    示例:

dtb.bin 签名流程

  • 主机工具需要 dtb.bin 文件的路径。
  • 主机工具需要 keycertificate 的路径(绝对路径或网络路径)来对镜像签名。
  • UEFI 安全启动需要 PE 格式的文件进行验证。dtb 等非 PE 文件无法使用 sbsign 签名,因为此签名工具要求输入 PE 格式的文件。
  • 主机工具使用 openssl 实用程序对 dtb 文件签名。请核对以下语法,其中 dsk1.key 为密钥,dsk1.crt 为证书:
    示例:
    此命令将 DTB 文件的签名添加到一个单独的文件(foo.sig)中,不会修改原始文件(foo.img)。因此,主机工具必须同时保留这两个文件,其中 *.sig 文件在 UEFI 安全启动验证期间使用。

多 DTB 支持

Qualcomm 支持基于相同硬件 SoC 的多个 Qualcomm 开发套件。例如,QCS6490 开发套件变体包括 RB3 Gen 2 Core 开发套件和 RB3 Gen 2 Vision 开发套件。 每个 Qualcomm 开发套件变体在内核中都有自己的 DTB。在启动期间,UEFI 会根据具体的 Qualcomm 开发套件变体选择合适的 DTB。为此,请按如下方式使用多 DTB 扁平镜像树(FIT)镜像:

生成多 DTB FIT 镜像

对于单个硬件 SoC 需要多个 DTB 的平台,Qualcomm Linux 支持生成基于 FIT 的多 DTB 镜像。这使 UEFI 能够在启动时根据检测到的硬件变体选择合适的 DTB。 对于支持 FIT 镜像的平台,多个 DTB 通过机器配置文件中的 KERNEL_DEVICETREE 变量列出。例如,以下来自 meta-qcom/conf/machine/rb3gen2-core-kit.conf 的代码片段为 RB3 Gen 2 Core 开发套件定义了两个 DTB:
这些 DTB 会在构建过程中合并为单个 FIT 镜像。
  1. 添加 DTB compatible 字符串:FIT 镜像中包含的每个 DTB 都必须有一个关联的 compatible 字符串。UEFI 在启动时使用这些 compatible 字符串选择正确的 DTB。
    • compatible 字符串在 meta-qcom/conf/machine/include/fit-dtb-compatible.inc 中定义。
    • 这些值必须参考以下位置提供的 DTB 元数据来推导:https://github.com/qualcomm-linux/qcom-dtb-metadata 对于 RB3 Gen 2 Core Kit 示例,请添加以下条目:
  1. 启用多 DTB 打包:要将生成的 FIT 镜像打包为 VFAT 镜像(dtb.bin),请在 meta-qcom/classes-recipe/image_types_qcom.bbclass 中设置以下变量:
    当此变量设置为 multi-dtb 时,构建系统会将包含 KERNEL_DEVICETREE 中列出的所有 DTB 的合并 FIT 镜像打包到 dtb.bin 中。

不支持 FIT 镜像的开发套件

某些平台不支持基于 FIT 的 DTB 选择。这包括某些 ride 开发套件,例如:
  • qcs9100-ride-sx
  • qcs8300-ride-sx
对于这些套件,只能将单个 DTB 打包到 dtb.bin 中。例如,以下来自 meta-qcom/conf/machine/qcs9100-ride-sx.conf 的代码片段列出了多个 DTB:
由于此套件不支持基于 FIT 的 DTB 选择,必须选择单个 DTB 作为默认值。请在同一机器配置文件中按如下方式设置 QCOM_DTB_DEFAULT 变量:
采用此设置后,只有 qcs9100-ride-r3.dtb 会被打包到 VFAT 镜像(dtb.bin)中并在启动期间使用。

DTB 分区

  • 生成的名为 dtb.bin 的 VFAT 镜像包含合并后的 DTB 镜像。Qualcomm 开发套件上有一个名为 dtb 的专用分区。请将 dtb.bin 烧录到此分区。
  • UEFI 会解析 dtb 分区中存在的合并 DTB,并为硬件选择匹配的 DTB。

后续步骤