启用安全启动时通过启动项运行AfuEfiX64.efi的技术问询
AMI AfuEfiX64.efi BIOS升级启动项问题排查与解决方案
问题背景
通常AMI的AfuEfiX64.efi BIOS升级工具需通过UEFI shell运行,安全启动禁用时可正常操作,但启用安全启动后无法访问UEFI shell。尝试用efibootmgr创建启动项直接运行签名版AfuEfiX64Signed.efi:
# 创建带参数的BIOS升级启动项 efibootmgr -C --disk /dev/nvme0n1 --part 1 --label "BiosUpgrader" --loader "\EFI\AfuEfix64Signed.efi" --unicode "fs:0/EFI/BIOS_UPDATE_FILE.BIN /p /b /n /x /k /RLC:F" # 设置下次重启优先启动该项目 efibootmgr -n 000X # X为实际创建的启动项编号
启动项创建成功,但从BIOS固件界面启动时,即使安全启动禁用,屏幕短暂黑屏后直接返回固件界面。推测该EFI应用依赖UEFI shell环境,因此自制EFI应用尝试调用UEFI shell执行.nsh脚本,但出现以下问题:
- 报错:
The UEFI Shell is not installed on this system: Not found - 继续执行时,
ShellExecute无论传入什么命令都返回Failed to run script: Not found - 在UEFI shell内执行该自制EFI应用时,无输出也无任何反应
问题解答
1. 是否有更优方法直接运行AfuEfiX64.efi,无需自制EFI文件包裹?
有两种更直接的可行方案:
- 修正启动项参数格式:AfuEfiX64.efi作为独立EFI应用,参数不需要UEFI shell的
fs:前缀,直接使用EFI文件系统的路径格式。比如将启动项参数改为\EFI\BIOS_UPDATE_FILE.BIN /p /b /n /x /k /RLC:F,同时确保AfuEfix64Signed.efi和BIOS升级文件都在ESP分区的对应路径下。 - 使用UEFI shell镜像作为启动项:将UEFI shell的EFI镜像(比如
ShellX64.efi)放到ESP分区,用efibootmgr创建启动项并指定自动执行脚本的参数,例如:
其中efibootmgr -C --disk /dev/nvme0n1 --part 1 --label "ShellBIOSUpgrader" --loader "\EFI\ShellX64.efi" --unicode "-nointerrupt -noconsolein -noconsoleout \EFI\bios-update.nsh"bios-update.nsh内容为:
这种方式利用原生UEFI shell环境,避免自制EFI应用的兼容性问题。AfuEfiX64.efi \EFI\BIOS_UPDATE_FILE.BIN /p /b /n /x /k /RLC:F reset -s
2. 如何获取EFI程序启动失败的详细原因?
可通过以下方式排查:
- 启用UEFI固件日志:进入BIOS设置,找到「UEFI Log」或「Firmware Log」选项并启用日志记录,重启尝试启动项后,查看日志中关于AfuEfiX64Signed.efi启动失败的具体错误码(比如
EFI_NOT_FOUND、EFI_ACCESS_DENIED等)。 - 添加调试输出:如果使用自制EFI应用,确保
Print输出能正常显示(部分BIOS启动时默认关闭控制台输出,可在BIOS中开启「UEFI Console Output」选项),或者将日志写入ESP分区的文件中,例如使用UefiLib的文件操作函数记录启动过程的状态和错误码。 - 验证文件完整性与路径:用UEFI shell手动执行
AfuEfix64Signed.efi和对应的BIOS文件,确认文件路径、权限(ESP分区需为FAT32格式,文件无损坏)、参数格式是否正确,排除文件本身的问题。
3. 从启动项启动时能否使用ShellExecute?脚本是否存在问题?
从启动项直接运行自制EFI应用时,无法直接使用ShellExecute,核心原因如下:
- 大部分UEFI固件默认不会预安装UEFI Shell协议(
gEfiShellProtocolGuid),只有当UEFI shell本身被加载时,才会注册该协议。因此自制EFI应用作为启动项运行时,系统中没有Shell协议,导致LocateProtocol失败。 - 你的脚本存在两个关键问题:
ShellInitialize函数仅用于初始化Shell库的环境,无法替代完整的UEFI shell加载流程。- 即使强行调用
ShellExecute,由于没有Shell协议存在,该函数无法找到执行环境,必然返回Not found错误。
如果必须通过自制EFI应用实现,正确的做法是:
- 在自制EFI应用中手动加载UEFI shell的EFI镜像(比如
ShellX64.efi),通过gBS->LoadImage和gBS->StartImage函数启动shell,并传递脚本参数。 - 或者直接在自制EFI应用中模拟AfuEfiX64.efi的调用逻辑,通过UEFI的文件系统协议读取BIOS升级文件,再调用AfuEfiX64.efi的入口函数(需了解其接口规范,兼容性较差,不推荐)。
内容的提问来源于stack exchange,提问作者zjeffer
相关产品推荐
相关产品推荐

