Step to UEFI (261)BootMenu插入自己的Application

在QEMU 的Boot Manager/Menu 中可以看到”EFI Internal Shell” 这个选项,选中之后会跳转到其中执行 Shell.efi,这次就尝试编代码在其中插入能够启动到自己Application的选项。

首先我们研究一下这个选项是如何插入的。在\ovmfpkg\library\platformbootmanagerlib\BdsPlatform.c 的 PlatformBootManagerAfterConsole()函数中有:

  //
  // Perform some platform specific connect sequence
  //
  PlatformBdsConnectSequence ();

  EfiBootManagerRefreshAllBootOption ();

  //
  // Register UEFI Shell
  //
  PlatformRegisterFvBootOption (
    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
    );

  RemoveStaleFvFileOptions ();
  SetBootOrderFromQemu ();

其中gUefiShellFileGuid 的定义在 \ShellPkg\ShellPkg.dec

  # FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf
  gUefiShellFileGuid              = {0x7c04a583, 0x9e3e, 0x4f1c, {0xad, 0x65, 0xe0, 0x52, 0x68, 0xd0, 0xb4, 0xd1}}

也可以在\ShellPkg\Application\Shell\Shell.inf 中看到

[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = Shell
  FILE_GUID                      = 7C04A583-9E3E-4f1c-AD65-E05268D0B4D1 # gUefiShellFileGuid
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

使用工具可以看到:

接下来我们着手设计一个自己的 Application 用于验证,需要特别注意的是,这个程序不能使用 SHELL 的任何Protocol和Service,因为调用它的时候没有 Shell。代码非常简单:

1. BootTest.c 如下

#include  <Uefi.h>
EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
        for (int i=0;i<1000;i++) {
                SystemTable->ConOut->OutputString(
                        SystemTable->ConOut,
                        L"www.lab-z.com\n");
        }

  
  return(0);
}

2. BootTest.inf如下:

[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = BootTest
  FILE_GUID                      = a912f198-7f0e-4803-b908-b757b806ec89
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 0.1
  ENTRY_POINT                    = UefiMain

#
#  VALID_ARCHITECTURES           = IA32 X64 IPF
#

[Sources]
  BootTest.c

[Packages]
  MdePkg/MdePkg.dec
  ShellPkg/ShellPkg.dec

[LibraryClasses]
  UefiLib
  UefiApplicationEntryPoint
  DebugLib

EDK2 202108 已经没有 AppPkg , 所以我们直接放在 ShellPkg 中。接下来修改代码如下:

1.\OvmfPkg\OvmfPkgX64.dsc 中,插入 INF 文件

    <PcdsFixedAtBuild>
      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
      gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
  }

  ShellPkg/Application/BootTest/BootTest.inf

!if $(SECURE_BOOT_ENABLE) == TRUE
  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
  OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
!endif

2.\OvmfPkg\OvmfPkgX64.fdf 中插入

!if $(TOOL_CHAIN_TAG) != "XCODE5"
INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
INF  ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
INF  OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF  ShellPkg/Application/Shell/Shell.inf
INF  ShellPkg/Application/BootTest/BootTest.inf

INF MdeModulePkg/Logo/LogoDxe.inf

#
# Network modules
#
!if $(E1000_ENABLE)
  FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
    SECTION PE32 = Intel3.5/EFIX64/E3522X2.EFI
  }

3. \OvmfPkg\Library\PlatformBootManagerLib\BdsPlatform.c 文件做插入 BootMenu的动作

定义一个 GUID,来自 BootTest.inf 中的FILE_GUID                    

EFI_GUID  gBootTest = {
	0xa912f198, 0x7f0e, 0x4803,
	{ 0xb9, 0x08, 0xb7, 0x57, 0xb8, 0x06, 0xec, 0x89 } };

插入动作:

  //
  // Perform some platform specific connect sequence
  //
  PlatformBdsConnectSequence ();

  EfiBootManagerRefreshAllBootOption ();
  DEBUG((DEBUG_INFO, "LABZTest_Start\n"));
  //
  // Register a Test Application
  //
  PlatformRegisterFvBootOption(
	  &gBootTest, L"LABZTest", LOAD_OPTION_ACTIVE
  );
  DEBUG((DEBUG_INFO, "LABZTest_End\n"));
  //
  // Register UEFI Shell
  //
  PlatformRegisterFvBootOption (
    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
    );

重新编译之后,可以用工具看到我们插入的 Application:

运行结果:

可以看到 BootMenu 中出现了我们设定的启动选项。

本文提到的用于测试的 BootTest:

发表回复

您的电子邮箱地址不会被公开。

CAPTCHAis initialing...