Run AfuEfiX64.efi BIOS upgrader as a boot entry instead of through UEFI shell, with secure boot enabled

huangapple go评论71阅读模式
英文:

Run AfuEfiX64.efi BIOS upgrader as a boot entry instead of through UEFI shell, with secure boot enabled

问题

  1. 有没有更好的方法来直接运行AfuEfiX64.efi程序,而不需要创建自己的EFI文件来包装它在UEFI shell内?

  2. 是否有办法获取更详细的信息,以了解为什么EFI程序无法作为启动项运行?

  3. 在从启动项启动时是否有可能使用ShellExecute(而不是通过UEFI shell运行)?或者我的脚本存在问题?

英文:

Usually, to use the AfuEfiX64.efi BIOS upgrader from AMI, you have to run the .efi file through the UEFI shell. This works with secure boot disabled, but the UEFI shell is not accessible when secure boot is enabled, so I have to run this EFI file through a boot entry instead by dynamically creating a boot entry with efibootmgr, like so:

# this creates the boot entry with the correct parameters to upgrade the 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"
# and then make sure it boots next time we restart
efibootmgr -n 000X # (X=number of created boot entry)

This works and creates the boot entry which I can run as if I start the boot loader for an operating system. When I try to boot into this created boot entry from the BIOS firmware interface, even with secure boot disabled, the screen goes dark for a second and then goes back to the firmware interface.

I believe this might happen because maybe the EFI application needs to be run inside of a UEFI shell? To fix this, I created my own EFI application that opens an EFI shell which then calls a .nsh script that runs the AfuEfiX64.efi program with the correct parameters:

#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: %r\n", Status);
    gBS->Stall(1000000);
    return Status;
  }

  // initialize the shell
  Status = ShellInitialize();
  if (EFI_ERROR(Status)) {
    Print(L"Failed to initialize the shell: %r\n", 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: %r\n", 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: %r\n", Status);
    // wait 5 seconds
    gBS->Stall(5000000);
    return Status;
  }

  return EFI_SUCCESS;
}

This doesn't seem to work:

  • I'm getting the error "The UEFI Shell is not installed on this system: Not found"
  • When proceeding, the ShellExecute function returns "Failed to run script: Not found", no matter what I put into the L"<command>" parameter
  • If I try to execute the above EFI application through the UEFI shell, nothing happens and it doesn't output anything.

So here are my questions:

  1. Is there a better way to directly run the AfuEfiX64.efi program, without creating my own EFI file to wrap it inside of a UEFI shell?
  2. Is there a way to get more verbose information for why the EFI program fails to run as a boot entry?
  3. Is it even possible to use ShellExecute when booting from a boot entry (instead of through the UEFI shell)? Or is there something wrong with my script?

答案1

得分: 1

有关安全性的一些话,首先,拥有系统上的已签名shell可以允许攻击者绕过安全启动,为了避免这种风险,您必须确保您使用的是一个没有允许内存或系统操作的脚本shell。

您可以构建一个脚本shell(级别1),创建一个带有加载选项的引导项,并将其用作AfuEfiX64.efi的包装器。

  • 克隆edk2
  • 按照设置步骤进行操作
  • 在ShellPkg\ShellPkg.dsc中创建一个新的shell构建配置,在它们之后已经有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包

  • 为级别1 shell创建一个新的引导项,带有所需的引导选项

-exit \EFI\AfuEfix64Signed.efi [Parameter]

这是我机器上的一个测试示例引导项,shell_echo.efi是ShellPkg中的ShellCTestApp:

FS0:\efi\uoe\&gt; bcfg boot dump -v
...
Option: 08. Variable: Boot0002
  Desc    - Shell (L1)
  DevPath - HD(2,GPT,88B7633D-4441-4F23-A535-3AE7FB88B9F6,0x109000,0x32000)/\EFI\UOE\shell_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-5C 00 73 00 68 00 65 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 2...
英文:

A word about security first, having a signed shell on your system can allow an attacker to bypass secure boot, to avoid this risk you must make sure that you are using a scripting shell without any command that allows memory or system manipulation.

You can build a scripting shell (level 1), create a boot entry with load options and use it as a wrapper for AfuEfiX64.efi.

  • Clone edk2

  • Follow the setup steps

  • Create a new shell build config in ShellPkg\ShellPkg.dsc, there are already 2 build configs, create the new one after them

     ShellPkg/Application/Shell/Shell.inf {
    &lt;Defines&gt;
    FILE_GUID = 9105952F-D171-4F1A-812E-F32B055668C5
    &lt;PcdsFixedAtBuild&gt;
    gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
    gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel|1
    gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0
    &lt;LibraryClasses&gt;
    NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
    

    }

  • Build the shell package

  • Create a new boot entry for the Level 1 shell with the required boot options

    -exit \EFI\AfuEfix64Signed.efi [Parameter]

An example boot entry from a test on my machine, shell_echo.efi is the ShellCTestApp from the ShellPkg:

FS0:\efi\uoe\&gt; bcfg boot dump -v
...
Option: 08. Variable: Boot0002
Desc    - Shell (L1)
DevPath - HD(2,GPT,88B7633D-4441-4F23-A535-3AE7FB88B9F6,0x109000,0x32000)/\EFI\UOE\shell_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...*

huangapple
  • 本文由 发表于 2023年4月11日 15:52:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75983592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定