QEMU启动OVMF shell超时分析

QEMU启动OVMF shell超时分析

实验环境

类型 描述
OVMF固件版本 edk2 20211219
QEMU版本 20260729
QEMU运行脚本内容 qemu-system-x86_64.exe -bios "OVMF.fd" -M "pc" -m 256 -cpu "qemu64" -boot order=dc -serial stdio -hda fat:rw:FAT

‍

运行现象

可以正常boot OVMF固件,但在QEMU使用的屏幕上打印">>Start PXE over IPv4"之后,大概会等待1min,才会进入UEFI shell界面。

‍

现象对应的代码路径

BDS 尝试启动 PXE 启动项时,走的是 EfiPxeLoadFile()​(PXE 驱动提供的 EFI_LOAD_FILE_PROTOCOL),执行顺序是:

  1. 介质检测 ​:NetLibDetectMediaWaitTimeout(..., PXEBC\_CHECK\_MEDIA\_WAITING\_TIME, ...)​,最多等 20 秒 网线/链路就绪。

  2. PxeBc->Start() ​:在 PxeBcImpl.c:129​ 打印 >>Start PXE over IPv4​,这里​只做初始化,不等待。

  3. PxeBcLoadBootFile → PxeBcDiscoverBootFile :真正耗时的是这一步里的 PxeBc->Dhcp(),即 DHCP 的 D.O.R.A. 过程。

    ‍

Root Cause分析:DHCP D.O.R.A. 超时

进入 PxeBcDhcp4Dora() 后,配置了 DHCP 重试参数:

c 复制代码
Config.DiscoverTryCount = PXEBC_DHCP_RETRIES;   // = 4
Config.DiscoverTimeout  = mPxeDhcpTimeout;      // = { 4, 8, 16, 32 } 秒
  • 超时表定义在 PxeBcDhcp4.c:28:UINT32 mPxeDhcpTimeout[4] = { 4, 8, 16, 32 };
  • 重试次数定义在 PxeBcImpl.h:69:#define PXEBC_DHCP_RETRIES 4

关键点 ​:QEMU 默认的 user-mode(SLIRP)网络​不会提供 DHCP/PXE 服务 ​,所以客户端发出 DHCP Discover 广播后永远等不到 Offer。于是按 4s → 8s → 16s → 32s 依次重发 4 次,累计等待 4+8+16+32 = 60 秒 后返回 EFI_TIMEOUT,PXE 启动失败,BDS 才转向下一个启动项。

也就是说,打印 >>Start PXE over IPv4​ 之后的"长时间停住",本质是在干等一个不存在的 DHCP 服务器,约 60 秒。如果虚拟机里配了多个网卡,每个网卡都会再重来一遍 60 秒。

‍

验证方法

  • 在 QEMU 日志里打时间戳:从打印 >>Start PXE over IPv4​ 到下一个启动项/报错,间隔应该接近 ​60 秒(若还叠加了介质检测,则是 20s + 60s)。

  • 观察是否打印 Station IP address is ...​(DHCP 成功才打印,PxeBcDhcp4.c:1741)------没有打印说明 DHCP 一直超时。

    ‍

解决办法

  1. 根本避免 PXE 尝试(推荐,最省事):

    • 用 -boot order=c(磁盘优先),让 PXE 不在启动顺序前段;
    • 或在 QEMU 命令行不给网卡指定 bootindex,配合 -boot strict=on,使网卡不进入 BootOrder;
    • 如果根本不需要网络启动,直接用 -net none / 不添加 -netdev。
  2. 确实需要网络启动:在宿主机配置 DHCP/PXE 服务器(如 dnsmasq),QEMU 的 SLIRP 不提供 PXE 服务,必须外接。

  3. 只想缩短卡顿时长 ​(改代码重编):把 mPxeDhcpTimeout​ 或 PXEBC\_DHCP\_RETRIES​ 调小(例如改成 {2, 4, 8}​ 或 retries=2),可显著减少 60s 等待,但这属于修改 UEFI 网络栈行为。

一句话:慢的原因是 UEFI 的 PXE 驱动在没有 DHCP 服务器的环境下按 4/8/16/32 秒做了 4 次 Discover 重试,累计约 60 秒 ,与 GetFrontPageTimeoutFromQemu​/PcdPlatformBootTimeOut 无关。

‍

最终选择方案

在qemu运行脚本中添加-net none,不再出现超时等待。

完整的QEMU运行脚本内容如下:

qemu-system-x86_64.exe -bios "OVMF.fd" -M "pc" -m 256 -cpu "qemu64" -boot order=dc -net none -serial stdio -hda fat:rw:FAT

‍

相关推荐
光视界6 小时前
友思特 ALE系列技术参数详解:UV波段的真实性能表现
经验分享·紫外光源
·present·6 小时前
CSAPP(lecture 4_01)
c语言·c++
爱吃火鸡面呀10 小时前
Spark RDD 行动算子(Action)详解
windows·ajax·spark
本地化文档10 小时前
llvm-libc-docs-l10n
c语言·github·gitcode·sphinx·llvm·crowdin
dlhto10 小时前
Windows 使用 Rufus 制作 AlmaLinux 10.2 启动 U 盘:从 ISO 下载到服务器安装
运维·服务器·windows
底层玩家老张11 小时前
45:1压缩、19.1倍查询:1956亿行时序数据复盘
数据库·经验分享·时序数据库·存储压缩·写入优化
Felven11 小时前
B. Collecting Game
c语言
Felven11 小时前
C. Removing Smallest Multiples
c语言·开发语言
小矮强11 小时前
输入凭证也没用?Windows 共享文件夹“来宾访问被安全策略阻止”
windows·经验分享
qingyunliushuiyu12 小时前
集团型企业数据治理系统选型,如何结合自身业务选适配款?
人工智能·经验分享