1. 搭建UEFI开发环境

任务目标

本案例完成UEFI开发的最小闭环:安装EDK2与交叉编译工具链,配置环境变量,编译一个打印Hello UEFI!的应用程序,并生成可在QEMU中启动的UEFI镜像验证运行。

环境与依赖

  • 操作系统:Ubuntu 22.04/24.04(x86_64)
  • EDK2:edk2-stable202311
  • 工具链:gcc、make、uuid-dev、nasm、qemu-system-x86_64、ovmf
sudo apt update
sudo apt install -y gcc make uuid-dev nasm qemu-system-x86 ovmf

EDK2源码与工具链配置

cd ~
git clone https://github.com/tianocore/edk2.git -b edk2-stable202311
cd edk2
git submodule update --init --recursive
make -C BaseTools
source edksetup.sh

编辑Conf/target.txt,设置以下关键项(其余保持默认):

ACTIVE_PLATFORM       = MdeModulePkg/MdeModulePkg.dsc
TARGET                = DEBUG
TARGET_ARCH           = X64
TOOL_CHAIN_TAG        = GCC5

最小UEFI应用程序

创建文件HelloWorld/HelloWorld.inf:

[Defines]
  INF_VERSION          = 0x00010005
  BASE_NAME            = HelloWorld
  FILE_GUID            = 9e6b9c9a-5c8e-4f2a-8b3d-1a2b3c4d5e6f
  MODULE_TYPE          = UEFI_APPLICATION
  VERSION_STRING       = 1.0
  ENTRY_POINT          = UefiMain

[Sources]
  HelloWorld.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib

创建文件HelloWorld/HelloWorld.c:

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  Print (L"Hello UEFI!\r\n");
  return EFI_SUCCESS;
}

编译与运行

# 在edk2根目录下执行
build

# 创建可启动UEFI镜像(含应用程序)
mkdir -p ~/uefi-run
cp Build/MdeModule/DEBUG_GCC5/X64/HelloWorld.efi ~/uefi-run/
cp /usr/share/OVMF/OVMF_CODE.fd ~/uefi-run/
cp /usr/share/OVMF/OVMF_VARS.fd ~/uefi-run/

# 创建启动菜单
cat > ~/uefi-run/startup.nsh << 'EOF'
HelloWorld.efi
EOF

# 运行QEMU
cd ~/uefi-run
qemu-system-x86_64 \
  -drive if=pflash,format=raw,readonly=on,file=OVMF_CODE.fd \
  -drive if=pflash,format=raw,file=OVMF_VARS.fd \
  -drive format=raw,file=fat:rw:~/uefi-run \
  -nographic

验证方法

QEMU启动后,OVMF固件会自动执行startup.nsh中的命令。观察串口输出:

  • 若屏幕显示Hello UEFI!,说明应用程序编译正确且能在UEFI环境中运行。
  • 若未显示,检查build输出是否有错误,确认HelloWorld.efi已生成且路径正确。

预期输出(由代码逻辑直接推出):

Hello UEFI!

常见问题

  • 编译报错找不到GCC5工具链:确认已执行source edksetup.sh,且Conf/target.txt中TOOL_CHAIN_TAG为GCC5。
  • QEMU无法启动:确认OVMF固件路径正确,OVMF_CODE.fd和OVMF_VARS.fd均已复制到运行目录。
  • startup.nsh未执行:确保fat:rw:指向的目录包含startup.nsh,且文件名拼写正确。