3. UEFI固件开发环境搭建:EDK2源码获取、编译环境配置(Windows/Linux)、模拟器运行

好,咱们进入第三章。说实话,很多初学者觉得UEFI开发难,其实有一半的功夫都花在环境搭建上。环境配不好,后面全是坑。我个人习惯先把EDK2源码拉下来,再配编译器,最后跑个模拟器验证——这套流程走通了,后面写代码才踏实。

3.1 EDK2源码获取

EDK2是TianoCore社区维护的开源项目,也是UEFI固件开发的事实标准。我建议直接从GitHub拉取稳定分支,别用master,那个太新,有时候会有兼容问题。

推荐分支:edk2-stable202311 或更新的稳定标签。我个人习惯用stable标签,因为经过社区测试,坑少。

3.1.1 通过Git克隆

git clone https://github.com/tianocore/edk2.git
cd edk2
git checkout edk2-stable202311
git submodule update --init --recursive

注意最后一步——子模块更新。EDK2依赖很多第三方库,比如CryptoPkg、MdeModulePkg里的某些组件。如果不更新子模块,编译时会报一堆头文件找不到的错误。我曾经有一次忘了跑这步,排查了半小时才发现是子模块没拉全。

3.1.2 目录结构速览

拉下来之后,你看到的目录大概是这样:

目录/文件 作用
MdePkg/ 核心定义:数据类型、协议、PPI、GUID等
MdeModulePkg/ 通用模块:BDS、Driver Binding、HII等
UefiCpuPkg/ CPU相关驱动和库
PcAtChipsetPkg/ 传统芯片组支持(8259、8254等)
OvmfPkg/ QEMU虚拟机固件,模拟器运行就靠它
edksetup.bat / edksetup.sh 环境初始化脚本(Windows/Linux)
Conf/target.txt 编译目标配置文件

嗯,这里要提醒一下:不要直接修改EDK2源码目录下的文件。你的代码应该放在自己的Package里,通过DSC文件引用。这是工程规范,也是避免合并冲突的好习惯。

3.2 编译环境配置

EDK2支持Windows和Linux两大平台。我两边都用过,说实话Linux下更顺手,但Windows也有它的优势——调试工具链更成熟。

3.2.1 Windows环境配置

Windows下需要装三样东西:Visual Studio、Python、NASM。

  1. Visual Studio 2019/2022:安装时勾选“使用C++的桌面开发”,编译器用VS自带的cl.exe。
  2. Python 3.x:EDK2的构建脚本依赖Python,建议装3.8以上版本。
  3. NASM:汇编器,用于编译汇编代码。下载后把nasm.exe所在目录加到PATH里。

小技巧:我习惯在Windows上装一个“Developer Command Prompt for VS”,然后在这个终端里执行EDK2的编译命令。这样环境变量自动配好,省事。

配置步骤:

# 打开VS开发者命令提示符
cd C:\edk2
edksetup.bat Rebuild
# 编辑 Conf\target.txt,设置:
#   ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc
#   TARGET = DEBUG
#   TARGET_ARCH = X64
#   TOOL_CHAIN_TAG = VS2022
build

我第一次配Windows环境时,卡在TOOL_CHAIN_TAG上。VS2019对应VS2019,VS2022对应VS2022,别写错了。还有,如果报“nasm not found”,八成是PATH没加对。

3.2.2 Linux环境配置

Linux下相对简单,装好gcc、make、python3、nasm就行。以Ubuntu为例:

sudo apt update
sudo apt install build-essential uuid-dev nasm python3 python3-pip
cd ~/edk2
make -C BaseTools
source edksetup.sh
# 编辑 Conf/target.txt,设置:
#   ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc
#   TARGET = DEBUG
#   TARGET_ARCH = X64
#   TOOL_CHAIN_TAG = GCC5
build

注意Linux下用source edksetup.sh而不是直接执行。这个脚本会设置EDK2相关的环境变量,比如WORKSPACE、PACKAGES_PATH。如果不source,build命令会找不到路径。

避坑指南:我曾经在Ubuntu 22.04上遇到gcc版本过高导致编译报错。EDK2对GCC5支持最好,如果你的系统默认gcc是12或13,建议装一个gcc-10并设置CC=gcc-10。或者用CLANG38工具链也行。

3.3 模拟器运行

环境配好、编译通过后,怎么验证?你手头不一定有真机,所以模拟器是首选。EDK2官方推荐两种方式:QEMU + OVMF 和 NT32模拟器。

3.3.1 QEMU + OVMF

OVMF(Open Virtual Machine Firmware)是EDK2为QEMU虚拟机准备的UEFI固件。编译OvmfPkg后,会生成OVMF.fd文件,这就是一个完整的UEFI BIOS。

运行命令:

# 安装QEMU
sudo apt install qemu-system-x86

# 启动UEFI固件
qemu-system-x86_64 -bios Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd \
                   -m 2048 \
                   -net none \
                   -nographic

你会看到UEFI Shell启动界面。输入map -r可以查看设备映射,输入fs0:可以访问文件系统。说白了,这就是一个完整的UEFI环境,你可以在这里测试自己的驱动或应用。

我的经验:调试阶段我习惯加-debugcon参数,把UEFI日志输出到文件。这样能看到DXE驱动加载顺序、Protocol安装情况,排查问题非常有用。

3.3.2 NT32模拟器(Windows专用)

NT32是EDK2提供的一个特殊平台——它把UEFI环境模拟成一个Windows应用程序。好处是调试方便,可以直接用Visual Studio断点调试。

配置方法:

# 在Conf/target.txt中设置:
#   ACTIVE_PLATFORM = Nt32Pkg/Nt32Pkg.dsc
build
# 编译成功后,运行:
Build/Nt32/DEBUG_VS2022/X64/Nt32.efi

会弹出一个控制台窗口,里面就是UEFI Shell。你可以加载自己的.efi文件,测试功能。不过NT32不支持硬件相关的Protocol(比如PCI、SMM),所以只适合纯逻辑测试。

3.4 本章知识体系

下面这张图概括了环境搭建的完整流程和关键节点:

UEFI开发环境搭建流程 UEFI开发环境搭建流程 1. 获取EDK2源码 2a. Windows环境配置 2b. Linux环境配置 3. 编译OvmfPkg/Nt32Pkg 4a. QEMU + OVMF 4b. NT32模拟器 5. 验证UEFI Shell启动 说明:Windows推荐NT32模拟器(支持VS调试),Linux推荐QEMU+OVMF(更接近真实硬件环境)

3.5 常见问题与排查

环境搭建过程中,我遇到过不少问题。挑几个典型的说说:

  • 编译报错“工具链未找到”:检查Conf/target.txt里的TOOL_CHAIN_TAG是否匹配实际安装的编译器版本。
  • 子模块更新失败:网络问题,建议用代理或手动下载子模块包放到edk2目录下。
  • QEMU启动后黑屏:检查OVMF.fd路径是否正确,或者加-vga std参数试试。
  • NT32启动报错“无法加载DLL”:缺少Visual C++运行库,安装VC++ redist即可。

调试小技巧:在UEFI Shell里输入ver可以查看固件版本,输入dh可以列出所有已安装的Protocol Handle。这两个命令我几乎天天用,排查驱动加载问题非常高效。

好了,环境搭建就讲到这里。你按照上面的步骤走一遍,应该能顺利看到UEFI Shell的界面。后面章节我们会基于这个环境,开始写真正的UEFI驱动和应用程序。