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,且文件名拼写正确。