2. BIOS自检(POST)与硬件探测实战
任务目标
使用QEMU虚拟机启动一个最小化系统,通过固件日志与串口输出观察BIOS自检(POST)流程,识别内存容量探测、显卡初始化、键盘控制器检测等硬件探测顺序,并理解各阶段输出信息的含义。
环境准备
- 安装QEMU:
apt-get install qemu-system-x86(Debian/Ubuntu)或yum install qemu(RHEL/CentOS) - 准备一个引导镜像:使用
OVMF.fd(UEFI固件)或默认SeaBIOS。本案例使用QEMU默认的SeaBIOS,无需额外下载。 - 需要
gcc和nasm编译一个最小引导扇区,用于触发完整的POST流程。
实现原理与代码
QEMU启动时默认加载SeaBIOS作为固件,执行完整的POST流程。为了观察POST输出,我们编译一个仅包含hlt指令的最小引导扇区,使系统在BIOS完成硬件探测后停在已知状态,便于捕获完整的POST日志。
; boot.asm - 最小引导扇区
BITS 16
ORG 0x7C00
start:
; 清屏并显示提示信息
mov ax, 0x0003
int 0x10
mov si, msg
print_loop:
lodsb
or al, al
jz done
mov ah, 0x0E
int 0x10
jmp print_loop
done:
; 停止CPU,等待重启
cli
hlt
jmp done
msg db 'POST completed. System halted.', 0
times 510-($-$$) db 0
dw 0xAA55
编译并制作启动镜像:
nasm -f bin boot.asm -o boot.bin
dd if=/dev/zero of=disk.img bs=512 count=1
dd if=boot.bin of=disk.img conv=notrunc
运行与观察POST输出
使用QEMU的-debugcon参数捕获BIOS调试输出,同时用-serial捕获串口输出:
qemu-system-x86_64 -drive file=disk.img,format=raw -debugcon file:post_log.txt -serial file:serial_log.txt -m 256 -display none
运行后查看post_log.txt,预期输出包含以下关键阶段(顺序固定):
SeaBIOS (version 1.13.0-1ubuntu1.1)
...
Booting from Hard Disk...
Booting from 0000:7c00
同时,在QEMU监视器(Ctrl+Alt+2)中执行info registers可确认CPU已停在hlt指令处。
硬件探测顺序识别
在post_log.txt中,硬件探测顺序体现为以下日志序列:
- 内存探测:日志中
Ram Size=0x10000000(256MB),对应-m 256参数 - 显卡初始化:
VGA detected或Display present,随后设置显示模式 - 键盘控制器:
PS/2 keyboard initialized,对应8042控制器检测 - 存储设备枚举:
Found 1 disks,识别到虚拟硬盘
要更详细地观察每个设备的探测时序,可添加-d int参数查看中断调用序列,或使用-trace events=acpi*跟踪ACPI表遍历过程。
验证方法
- 通过条件:
post_log.txt中按顺序出现内存容量、显卡、键盘、磁盘的探测记录,且serial_log.txt为空(无错误输出) - 功能验证:QEMU监视器中执行
info status显示VM status: paused (halted),证明POST完成后系统正确停在引导扇区 - 对比实验:将
-m参数改为512,重新运行,观察Ram Size值变化,确认内存探测与配置一致
常见问题
- 若
post_log.txt为空:确认QEMU版本支持-debugcon,或改用-boot order=a强制从硬盘引导 - 若未显示键盘初始化:部分QEMU版本默认不启用PS/2控制器,添加
-device piix3-usb-uhci或-machine q35可改变设备拓扑 - 引导扇区无法启动:检查
disk.img是否为512字节且以0x55AA结尾,用xxd disk.img | tail -1确认