UEFI Bootloader 全方位解读


📖 推荐博主书籍:《Yocto项目实战教程:高效定制嵌入式Linux系统
🎥 更多学习视频请关注 B 站:嵌入式Jerry


UEFI Bootloader 全方位解读

面向嵌入式与服务器双场景,聚焦工程师实操所需:清晰的概念边界、启动链路、关键配置、常用工具、与 U‑Boot 的差异、以及在 Jetson Orin/通用 ARM64/PC 的落地路径。


在这里插入图片描述

1. 什么是 UEFI?

UEFI(Unified Extensible Firmware Interface)是操作系统与平台固件之间的标准化接口与执行环境。与传统 BIOS 相比,UEFI 提供:

  • 统一的启动与运行时服务(Boot Services / Runtime Services)
  • 标准化的磁盘分区(GPT)与 EFI 系统分区(ESP, FAT32)
  • 可扩展的驱动与应用模型(EFI Drivers / EFI Applications)
  • 安全启动链(Secure Boot:PK/KEK/db/dbx)

一句话:UEFI 是“标准化的固件层”,在 OS 启动前完成硬件初始化、提供统一接口,最终把控制权交给内核(Linux/Windows/BSD 等)。


2. 启动链路概览(抽象模型)

ROM →(SoC Early Boot: MB1/MB2/BL1…)→ UEFI 固件
   →(Boot Services:定位并加载 EFI 应用/引导器)
   → Linux 内核(EFI Stub)/ GRUB / systemd-boot / Shim
   → 传递 ACPI/Device Tree、cmdline、initrd
   → 进入操作系统
  • EFI 应用可以是:

    • 直接使用 EFI Stub 的 Linux 内核(把内核当作一个 EFI 程序启动)
    • 通用引导器:GRUBsystemd-bootGRUB+Shim(安全启动)
  • 平台描述:x86 多用 ACPI;ARM 服务器与部分嵌入式常用 Device Tree(DTB),也逐步支持 ACPI。


3. 核心概念速览

  • EFI System Partition(ESP):FAT32 分区,放置 \EFI\Vendor\*.efi 与启动文件(AArch64 设备的默认回退路径:\EFI\BOOT\BOOTAA64.EFI)。
  • NVRAM 启动变量Boot####BootOrderBootNext,由固件持久化保存,efibootmgr 可管理。
  • EFI Stub:Linux 内核内建的 UEFI 入口,使内核可作为 *.efi 直接被 UEFI 加载;可通过内核命令行传入 DTB 与 initrd。
  • Secure Boot:固件只运行受信任的已签名 EFI 映像。常见路径:Shim → GRUB/systemd-boot → Linux,或直接签名后的 vmlinuz.efi

4. 工程师常用:最小可行启动(EFI Stub 直启)

4.1 准备 ESP 分区

# 假设目标磁盘 /dev/sdX
parted /dev/sdX mklabel gpt
parted /dev/sdX mkpart EFI fat32 1MiB 513MiB
parted /dev/sdX set 1 esp on
mkfs.vfat -F32 -n EFI /dev/sdX1
mkdir -p /mnt/esp && mount /dev/sdX1 /mnt/esp

4.2 放置文件与路径约定(AArch64)

/mnt/esp/EFI/BOOT/BOOTAA64.EFI      ← 引导入口(回退路径)
/mnt/esp/EFI/Linux/vmlinuz.efi      ← EFI Stub 内核(可直接被固件执行)
/mnt/esp/EFI/Linux/initrd.img       ← 可选:initramfs
/mnt/esp/EFI/Linux/tegra.dtb        ← 可选:DTB(或由固件传入)

4.3 创建/查看启动项

# 创建启动项(示例:NVMe 第 1 分区为 ESP)
efibootmgr -c -d /dev/nvme0n1 -p 1 \
  -L "Linux EFI Stub" \
  -l '\\EFI\\Linux\\vmlinuz.efi' \
  -u 'root=UUID=<rootfs-uuid> rw \
      initrd=\\EFI\\Linux\\initrd.img \
      devicetree=\\EFI\\Linux\\tegra.dtb \
      console=ttyS0,115200n8'

# 查看启动顺序与条目
efibootmgr -v

UEFI 文件路径使用 反斜杠\\),注意大小写与分区号。


5. 工程师常用:采用通用引导器(GRUB / systemd-boot)

  • GRUB:功能全面、兼容性强,适合多系统/复杂菜单;支持 DTB/ACPI、LUKS、网络等。
  • systemd-boot:轻量,基于 simple boot protocol,配合内核 EFI Stub 使用简洁高效。
  • Shim(安全启动):由微软签名的最小加载器,固件验证 Shim → Shim 验证 GRUB/内核。Linux 发行版普遍采用。

放置规则(AArch64):

  • \EFI\BOOT\BOOTAA64.EFI:回退入口,可指向 Shim/GRUB/systemd-boot。
  • Vendor 路径:\EFI\<Vendor>\*.efi,引导器与配置文件按其文档组织。

6. 安全启动(Secure Boot)与签名

6.1 概念

  • PK/KEK/db/dbx:平台密钥、密钥交换密钥、允许名单、黑名单。
  • 目标:只运行受信任的 EFI 映像(引导器、内核、驱动)。

6.2 开发常用签名流程(示意)

# 用 sbsigntool 对内核/引导器签名(示例)
sbsign --key PK.key --cert PK.crt \
       --output vmlinuz.signed.efi vmlinuz.efi
  • 使用 Shim:由固件验证 Shim,后续验证权交给 Shim/MOK(Machine Owner Key)体系,开发调试更灵活。

7. 设备树 / ACPI 的传递

  • ARM/嵌入式常见:通过 EFI Stub 的 devicetree= 指定 DTB,或由固件加载 DTB 传递给内核。
  • ARM 服务器 / x86:ACPI 更常见;Linux 内核从 UEFI 接收 ACPI 表。

建议:在同一平台内保持一种主路径(DTB 或 ACPI),避免混杂。


8. Jetson Orin 的要点(结合 L4T 经验)

  • Orin 使用 UEFI 固件(见出厂包中的 uefi_jetson.binBOOTAA64.EFI)。
  • 设备端一般使用 EFI Stub 或通用引导器加载 Linux;部分发行包保留 extlinux.conf 兼容以方便内核参数与多内核切换(厂商实现差异化)。
  • 刷机与签名由 tegraflashtegrasign 及 BUP 工具链完成;工程师侧重修改的是 ESP 内容、内核/DTB/initrd、引导器配置

9. 与 U‑Boot 的对比(工程取舍)

维度UEFIU‑Boot
标准化高:统一接口/变量/分区/服务低:高度可裁剪,接口随移植而异
生态PC/Server/发行版原生支持嵌入式/SoC 广泛,社区强
启动器EFI Stub / GRUB / systemd-boot / ShimU‑Boot 脚本/菜单,extlinux/grub 兼容亦可移植
安全启动体系成熟,厂商与发行版齐备可实现,但多为厂商/方案方定制
调试EFI Shell、NVRAM、统一日志接口命令行强大,外设覆盖广,移植灵活
适用需要与通用 OS 生态无缝衔接需要深度定制、快速移植与硬件 bring‑up

实务建议:

  • 面向产品/通用 OS:优先 UEFI(安全链、生态、量产一致性)。
  • 早期 bring‑up/高度定制:U‑Boot 往往更高效,后期再迁移 UEFI。

10. 常见操作清单(Cheat‑Sheet)

创建 ESP(FAT32)

parted /dev/sdX mklabel gpt
parted /dev/sdX mkpart EFI fat32 1MiB 513MiB
parted /dev/sdX set 1 esp on
mkfs.vfat -F32 -n EFI /dev/sdX1

挂载与放置文件

mount /dev/sdX1 /mnt/esp
mkdir -p /mnt/esp/EFI/BOOT /mnt/esp/EFI/Linux
cp BOOTAA64.EFI /mnt/esp/EFI/BOOT/
cp vmlinuz.efi initrd.img tegra.dtb /mnt/esp/EFI/Linux/

创建启动项

efibootmgr -c -d /dev/sdX -p 1 \
  -L "Linux" -l '\\EFI\\Linux\\vmlinuz.efi' \
  -u 'root=UUID=<uuid> rw initrd=\\EFI\\Linux\\initrd.img \
      devicetree=\\EFI\\Linux\\tegra.dtb console=ttyS0,115200n8'

查看/调整启动顺序

efibootmgr -v
# 置顶条目(示例 Boot0007)
efibootmgr -o 0007,0001,0002

签名(示例)

sbsign --key PK.key --cert PK.crt \
       --output vmlinuz.signed.efi vmlinuz.efi

11. 调试与排错

  • 串口日志:确保 UEFI console 指向板载 UART(例如 ttyS0/ttyAMA0/ttyTHS*),Kernel cmdline 添加 console=
  • EFI Shell 工具map(查看设备/分区映射)、bcfg(管理启动项)、dmpstore(读写 NVRAM 变量)、memmap(内存分布)。
  • NVRAM 丢失:RTC/NVRAM 断电后启动项丢失,依赖 BOOTAA64.EFI 回退路径与自动发现;必要时在系统启动后用 efibootmgr 重建。
  • 路径大小写与分隔符:UEFI 使用 FAT反斜杠;Linux 下复制文件要注意大小写与转义。
  • DTB/ACPI 冲突:保持单一路径(DTB 或 ACPI),并确保内核配置匹配。

12. 在 Yocto/发行版中的落地提示

  • Yocto:在 wic kickstart 使用 bootimg-efi 源,自动创建 ESP 并放置引导器/内核;镜像后期可用 wic ls/挂载检查路径。
  • 发行版:多数提供现成的 Shim/GRUB/systemd-boot 工具链;自定义内核时关注签名与 EFI/Linux 目录结构。
  • Jetson Orin:固件与刷机链路由 NVIDIA 提供,系统侧关注 ESP 内容与内核/DTB/引导器配置即可。

13. FAQ(工程师高频问题)

Q1:一定要 GRUB 吗?
A:不一定。EFI Stub 可直接启动内核;复杂菜单/多系统/加密场景,GRUB/systemd-boot 更合适。

Q2:Secure Boot 下怎样调试自编译内核?
A:使用 Shim + MOK 导入自签名证书,或在开发版固件中导入测试密钥;将 vmlinuz.efi 与引导器签名后再放入 ESP。

Q3:ARM 平台 DTB 怎么传?
A:常见做法是 devicetree=\\EFI\\Linux\\xxx.dtb 或由固件传入;确保 DTB 与内核版本匹配。

Q4:启动项总是被清空?
A:检查电池/RTC/NVRAM;保留 \EFI\BOOT\BOOTAA64.EFI 作为兜底入口,系统启动后用 efibootmgr 重建。


14. 结语

UEFI 把“平台差异”吸收到固件层,用标准化接口连接到通用 OS 与安全链。对于需要 安全、可维护、生态友好 的产品形态,UEFI 值得作为首选;而在原型阶段或重度定制,U‑Boot 的灵活性依然无可替代。将两者结合在项目生命周期的不同阶段,往往是更务实的工程方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值