通常,使用AfuEfiX64。从AMI的BIOS升级程序,你必须通过UEFI shell运行。efi文件。这可以在禁用安全引导的情况下工作,但是当启用安全引导时,UEFI shell是不可访问的,所以我必须通过一个引导条目来运行这个EFI文件,而不是通过动态地创建一个带有efibootmgr
的引导条目,如下所示:
# this creates the boot entry with the correct parameters to upgrade the BIOS
efibootmgr -C --disk /dev/nvme0n1 --part 1 --label "BiosUpgrader" --loader "EFIAfuEfix64Signed.efi" --unicode "fs:0/EFI/BIOS_UPDATE_FILE.BIN /p /b /n /x /k /RLC:F"
# and then make sure it boots next time we restart
efibootmgr -n 000X # (X=number of created boot entry)
这可以工作并创建引导条目,我可以像启动操作系统的引导加载程序一样运行它。当我尝试从BIOS固件界面引导到这个创建的引导项时,即使禁用了安全引导,屏幕也会变黑一秒钟,然后又回到固件界面。
我相信这可能会发生,因为也许EFI应用程序需要在UEFI外壳内运行?为了解决这个问题,我创建了自己的EFI应用程序,它打开一个EFI shell,然后调用一个运行AfuEfiX64的.nsh脚本。具有正确参数的Efi程序:
#include <Guid/FileInfo.h>
#include <Library/FileHandleLib.h>
#include <Library/PcdLib.h>
#include <Library/ShellLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiShellLib/UefiShellLib.h>
#include <Protocol/EfiShellEnvironment2.h>
#include <Protocol/EfiShellInterface.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/Shell.h>
#include <Protocol/ShellParameters.h>
#include <Uefi.h>
EFI_STATUS
EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) {
// Get the loaded image protocol for the current image
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_STATUS Status = gBS->HandleProtocol(
ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
if (EFI_ERROR(Status)) {
Print(L"Failed to get loaded image protocol: %rn", Status);
gBS->Stall(1000000);
return Status;
}
// initialize the shell
Status = ShellInitialize();
if (EFI_ERROR(Status)) {
Print(L"Failed to initialize the shell: %rn", Status);
gBS->Stall(1000000);
// return Status;
}
// Check whether the UEFI Shell protocol is present
Status = gBS->LocateProtocol(&gEfiShellProtocolGuid, NULL,
(VOID **)&gEfiShellProtocol);
if (EFI_ERROR(Status)) {
Print(L"The UEFI Shell is not installed on this system: %rn", Status);
gBS->Stall(1000000);
// return Status;
}
// The UEFI Shell is installed on this system, run the script
ShellExecute(ImageHandle, L"bios-update.nsh", FALSE, NULL, &Status);
if (EFI_ERROR(Status)) {
Print(L"Failed to run script: %rn", Status);
// wait 5 seconds
gBS->Stall(5000000);
return Status;
}
return EFI_SUCCESS;
}
这似乎不工作:
- 我得到错误" UEFI Shell未安装在此系统上:not found">
- 继续时,ShellExecute函数返回"Failed to run script: Not found",无论我在
L"<command>"
参数 中输入什么 - 如果我尝试通过UEFI shell执行上述EFI应用程序,没有任何事情发生,它不输出任何东西。
我的问题是:
- 是否有更好的方法直接运行AfuEfiX64。efi程序,没有创建我自己的efi文件来包装它在UEFI外壳内?
- 是否有一种方法可以获得更详细的信息,为什么EFI程序不能作为启动项运行?
- 是否有可能使用ShellExecute从启动项启动时(而不是通过UEFI shell)?还是我的剧本有问题?
首先说一下安全性,在您的系统上使用签名shell可以允许攻击者绕过安全引导,为了避免这种风险,您必须确保您使用的脚本shell没有任何允许内存或系统操作的命令。
您可以构建一个脚本shell(级别1),创建一个带有加载选项的引导条目,并将其用作AfuEfiX64.efi的包装器。
-
克隆edk2
-
遵循设置步骤
-
在ShellPkgShellPkg中创建一个新的shell构建配置。Dsc,已经有2个构建配置,在它们之后创建一个新的
ShellPkg/Application/Shell/Shell.inf { <Defines> FILE_GUID = 9105952F-D171-4F1A-812E-F32B055668C5 <PcdsFixedAtBuild> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel|1 gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0 <LibraryClasses> NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
}
-
构建shell包
-
为Level 1 shell创建一个新的启动项,包含所需的启动选项
退出 EFI AfuEfix64Signed。efi(参数)
来自我的机器上的一个测试的示例引导条目,shell_echo。efi是来自ShellPkg的ShellCTestApp:
FS0:efiuoe> bcfg boot dump -v
...
Option: 08. Variable: Boot0002
Desc - Shell (L1)
DevPath - HD(2,GPT,88B7633D-4441-4F23-A535-3AE7FB88B9F6,0x109000,0x32000)/EFIUOEshell_l1.efi
Optional- Y
00000000: 2D 00 65 00 78 00 69 00-74 00 20 00 2D 00 6E 00 *-.e.x.i.t. .-.n.*
00000010: 6F 00 6D 00 61 00 70 00-20 00 5C 00 65 00 66 00 *o.m.a.p. ..e.f.*
00000020: 69 00 5C 00 75 00 6F 00-65 00 5C 00 73 00 68 00 *i..u.o.e..s.h.*
00000030: 65 00 6C 00 6C 00 5F 00-65 00 63 00 68 00 6F 00 *e.l.l._.e.c.h.o.*
00000040: 2E 00 65 00 66 00 69 00-20 00 54 00 65 00 73 00 *..e.f.i. .T.e.s.*
00000050: 74 00 20 00 31 00 20 00-32 00 20 00 48 00 65 00 *t. .1. .2. .H.e.*
00000060: 6C 00 6C 00 6F 00 00 00- *l.l.o...*