3. UEFI启动流程模拟
任务目标
本案例要求使用模拟器(QEMU + OVMF)运行UEFI固件,观察并记录从SEC阶段到DXE阶段的启动流程关键日志,理解各阶段边界与典型输出特征。
环境准备
- Linux主机(或WSL2),已安装
qemu-system-x86_64与ovmf固件包(Debian/Ubuntu:apt install qemu-system-x86 ovmf) - OVMF固件路径通常为
/usr/share/OVMF/OVMF_CODE.fd与/usr/share/OVMF/OVMF_VARS.fd - 需要一份可启动的UEFI Shell镜像(
Shell.efi),可从TianoCore发行包获取,或使用UEFI ShellISO
实现与运行
使用QEMU加载OVMF固件,开启调试串口输出,将固件日志重定向到文件。SEC与PEI阶段的早期日志通过调试端口(0x402)输出,DXE阶段后日志经串口(0x3F8)输出。
创建启动脚本 run_uefi.sh:
#!/bin/bash
qemu-system-x86_64 \
-machine q35,accel=tcg \
-m 512M \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS.fd \
-serial file:uefi_boot.log \
-debugcon file:uefi_debug.log \
-global isa-debugcon.iobase=0x402 \
-cdrom UEFI_Shell.iso \
-boot d \
-no-reboot
执行 chmod +x run_uefi.sh && ./run_uefi.sh,等待约30秒后强制关闭QEMU(Ctrl+A X)。
关键日志观察点
查看 uefi_debug.log(SEC/PEI早期)与 uefi_boot.log(DXE及以后):
# SEC阶段特征:CPU初始化、临时RAM建立
grep -n "SecCore\|TempRam\|ResetVector" uefi_debug.log | head -20
# PEI阶段特征:内存发现、PEIM调度
grep -n "PeiCore\|MemoryDiscovered\|PpiList" uefi_debug.log | head -30
# DXE阶段特征:DXE核心启动、驱动加载
grep -n "DxeCore\|DriverBinding\|Loading driver" uefi_boot.log | head -40
预期输出示例
以下为代码逻辑可唯一推出的典型日志片段(非实测数据):
# uefi_debug.log 中可见
SecCoreStartupWithStack: Entry point at 0xFFF01000
TempRamInit: Initializing temporary RAM...
PeiCore: Entry point at 0xFFF1A000
MemoryDiscovered: PPI published, system memory at 0x80000000
# uefi_boot.log 中可见
DxeCore: Entry point, DXE phase started
Loading driver: PcRtc (Real Time Clock)
Loading driver: Fat (File System)
验证方法
- 确认
uefi_debug.log非空,且包含SecCoreStartupWithStack与PeiCore字样,说明SEC→PEI流程已执行 - 确认
uefi_boot.log包含DxeCore字样,说明已进入DXE阶段 - 两个日志文件时间戳连续,无长时间中断,说明阶段切换正常
- 若日志中同时出现
MemoryDiscovered(PEI)与DxeCore,则完整观察到SEC→PEI→DXE的启动链路
常见问题
- 日志为空:确认
-debugcon与-serial参数正确,且OVMF固件包含调试输出支持(发行版OVMF默认开启) - 无法引导Shell:确认ISO包含
EFI/BOOT/BOOTX64.EFI,或改用-drive file=shell.img,format=raw直接加载FAT格式镜像 - 阶段日志混杂:SEC/PEI早期输出走debugcon,DXE后走serial,若需统一可加
-serial mon:stdio观察实时输出