4、日志查看工具:bcfg、EFI Shell 与 efibootmgr

日志拿到了,怎么读?怎么查?

这是很多初学者卡住的地方。说实话,我第一次接触 UEFI 启动日志时,面对满屏的十六进制和 GUID,也是一脸懵。后来我发现,关键不在于「看」,而在于「查」——用对工具,日志自己会说话。

这一章,我带你过一遍三个最实用的日志查看工具:bcfg、EFI Shell 和 efibootmgr。它们分别对应 UEFI 固件内部、Shell 环境和 Linux 用户态。你想想看,不管你在哪个环节出问题,总有一款工具能帮你定位。

4.1 bcfg:固件里的瑞士军刀

bcfg 是 UEFI Shell 内置的启动配置管理命令。我个人习惯把它叫做「固件里的注册表编辑器」——它能直接读写 NVRAM 中的启动项。

核心能力:bcfg 可以查看、添加、删除、修改启动项和驱动项。在安全启动调试中,我主要用它来检查签名数据库的加载顺序。

4.1.1 查看启动项列表

进入 UEFI Shell 后,直接敲:

Shell> bcfg boot dump

输出大概长这样:

Option: 00.00    —  EFI Internal Shell
  File: \EFI\Shell.efi
  RC:   Success

Option: 01.00    —  Windows Boot Manager
  File: \EFI\Microsoft\Boot\bootmgfw.efi
  RC:   Success

Option: 02.00    —  Ubuntu
  File: \EFI\ubuntu\shimx64.efi
  RC:   Success

每一行就是一个启动项。注意那个 RC 字段——它表示上次启动该条目时的返回码。如果看到 Not Found 或 Security Violation,基本就是安全启动在报错了。

我的小技巧:如果某个启动项显示 Security Violation,别急着重装系统。先用 bcfg boot dump -v 查看详细签名信息,八成是证书过期或镜像被篡改。

4.1.2 添加与删除启动项

添加一个手动启动项:

Shell> bcfg boot add 3 fs0:\EFI\test\test.efi "Test Boot"

删除一个启动项:

Shell> bcfg boot rm 2

我曾经在调试一台国产服务器时,发现 NVRAM 里塞了 30 多个废弃启动项,导致启动菜单加载极慢。用 bcfg boot rm 一个个清掉后,开机速度从 45 秒降到了 12 秒。嗯,有时候问题就这么简单。

4.2 EFI Shell:命令行下的全貌

EFI Shell 本身就是一个强大的日志查看环境。它不像 bcfg 那样只关注启动项,而是能让你看到整个固件运行时的状态。

4.2.1 查看系统表与协议

我最常用的几个命令:

  • devtree — 显示设备树,能看到所有 UEFI 驱动的加载情况
  • drivers — 列出所有已加载的 UEFI 驱动及其状态
  • dh — 显示所有句柄(Handle)及其绑定的协议

举个例子,当安全启动验证失败时,我会先跑 dh -d 查看 EFI_SECURITY_ARCH_PROTOCOL 是否被正确安装:

Shell> dh -d
...
Handle 0x3B
  Image Device Path
  Loaded Image Protocol
  **EFI_SECURITY_ARCH_PROTOCOL**  ← 这个必须有
  EFI_SECURITY2_ARCH_PROTOCOL
...

如果看不到这两个安全协议,那说明固件压根没启用安全启动——你后面再怎么折腾签名都没用。

4.2.2 查看 NVRAM 变量

安全启动的签名数据库都存储在 NVRAM 变量中。用 dmpstore 可以导出所有变量:

Shell> dmpstore -all

但输出太长了。我一般只关注这几个:

变量名 GUID 作用
SecureBoot 8be4df61-93ca-11d2-aa0d-00e098032b8c 当前安全启动状态(0=关闭,1=开启)
SetupMode 同上 是否处于设置模式(1=可自定义签名)
db d719b2cb-3d3a-4596-a3bc-dad00e67656f 允许的签名/证书数据库
dbx 同上 禁止的签名/证书数据库
KEK 8be4df61-93ca-11d2-aa0d-00e098032b8c 密钥交换密钥,用于更新 db/dbx

避坑指南:我曾经在调试时直接用 dmpstore 把 NVRAM 全部导出到文件,然后试图用文本编辑器修改再写回去。结果固件直接变砖。记住,NVRAM 变量有校验和依赖关系,不要手动修改!

4.3 efibootmgr:Linux 下的远程遥控

很多时候你进不了 UEFI Shell——比如系统已经装好了,或者你远程登录服务器。这时候 efibootmgr 就是你的救星。

4.3.1 安装与基本用法

在大多数 Linux 发行版上:

# Debian/Ubuntu
sudo apt install efibootmgr

# RHEL/CentOS
sudo yum install efibootmgr

查看当前启动项:

$ sudo efibootmgr -v
BootCurrent: 0001
Timeout: 2 seconds
BootOrder: 0001,0002,0003
Boot0001* Windows Boot Manager  HD(1,GPT,...)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
Boot0002* Ubuntu  HD(1,GPT,...)/File(\EFI\ubuntu\shimx64.efi)
Boot0003* UEFI Shell  HD(1,GPT,...)/File(\EFI\Shell.efi)

注意那个 BootCurrent——它告诉你当前是从哪个条目启动的。如果这个值和你想的不一样,那说明启动顺序有问题。

4.3.2 安全启动相关操作

efibootmgr 还能直接操作安全启动的签名数据库。我个人觉得这是它最强大的地方:

# 查看安全启动状态
$ sudo efibootmgr -v | grep SecureBoot
SecureBoot: enabled

# 查看当前签名数据库
$ sudo efibootmgr -v --db
$ sudo efibootmgr -v --dbx

添加一个签名到 db 数据库:

$ sudo efibootmgr -D -d /dev/nvme0n1 -p 1 -L "MyCert" -l \EFI\test\mycert.cer

这个命令的意思是:把 mycert.cer 添加到 db 数据库中。注意 -D 参数表示操作的是 db,-d 和 -p 指定 EFI 系统分区所在的磁盘和分区。

为什么推荐 efibootmgr? 因为它不需要重启就能操作 NVRAM。我在调试远程服务器时,经常用 SSH 连上去,直接修改启动项或签名数据库,改完再重启验证。省去了来回跑机房的麻烦。

4.4 三款工具对比

说了这么多,你可能想问:到底该用哪个?

我的建议是:看场景。

工具 运行环境 最佳使用场景 局限性
bcfg UEFI Shell 固件调试、启动项管理 需要进入 Shell,无法远程使用
EFI Shell UEFI Shell 查看系统表、协议、NVRAM 变量 命令较多,学习曲线略陡
efibootmgr Linux 用户态 远程调试、批量操作、脚本化 依赖 Linux 内核的 efivars 支持

说白了,如果你人在机器前,用 bcfg 和 EFI Shell 最直接;如果你远程操作,efibootmgr 是唯一选择。我自己的习惯是:先用 efibootmgr 做初步诊断,再进 Shell 做深度排查。

4.5 本章知识体系

下面这张图帮你理清三个工具的关系和适用场景:

日志查看工具知识体系 bcfg EFI Shell efibootmgr 功能 • 启动项增删改查 • 驱动项管理 • 返回码检查 功能 • 设备树查看 • 协议/句柄检查 • NVRAM 变量导出 功能 • 远程启动项管理 • 签名数据库操作 • 脚本化批量处理 适用:固件调试 需进入 UEFI Shell 适用:深度排查 需进入 UEFI Shell 适用:远程运维 Linux 用户态运行 推荐流程:efibootmgr 初诊 → Shell 深查