virt,opensbi,dtb
QEMU RISC-Vvirt机器所谓的“自带 OpenSBI”,并不是一个独立的文件,而是直接编译在 QEMU 可执行文件内部的二进制代码。你无法直接在磁盘上找到一个名为opensbi-riscv64-virt-fw_jump.bin的独立文件。
🔍 为什么找不到这个文件?
在 QEMU 源码的hw/riscv/virt.c中,确实定义了默认固件名称为opensbi-riscv64-virt-fw_jump.bin,但这是作为内置资源处理的:
编译时嵌入:在构建 QEMU 时,该固件二进制文件会被转换为 C 数组(或直接链接),并编译进
qemu-system-riscv64这个二进制程序中。运行时加载:当你启动 QEMU 且不指定
-bios(或使用-bios default)时,QEMU 会从自己的内存中提取这段代码加载到客户机的 ROM 区域(地址0x1000),而不是从磁盘读取文件。
📁 如果你需要“看得见”的 OpenSBI 文件
为了调试或自定义引导流程(例如使用-bios指定路径),你需要从外部获取独立的 OpenSBI 二进制文件。通常有以下来源:
来源 | 典型路径(Linux 发行版) | 说明 |
|---|---|---|
系统包管理器 |
| 安装 |
QEMU 源码树 |
| 仅在编译 QEMU 的构建目录中可见,是内置固件的“本体”。 |
官方预编译 |
| 从 RISC-V OpenSBI 官网下载的预编译包。 |
💡 实用建议
默认使用:如果你只是跑内核,直接不指定
-bios即可,QEMU 会自动使用内置版本,无需操心文件路径。自定义版本:如果你想使用特定版本的 OpenSBI(如支持新 SBI 扩展),请安装系统的
opensbi包,然后在启动命令中显式指定:qemu-system-riscv64 -machine virt -bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.elf -kernel your_kernel
和 OpenSBI 的情况类似,QEMU RISC-Vvirt机器没有独立的、预编译好的 DTB 文件存放在磁盘上。它是 QEMU 在启动时根据你的命令行参数(如内存大小、CPU 数量)动态生成的。
🔍 为什么找不到.dtb文件?
QEMU 的virt机器定义(hw/riscv/virt.c)中包含了一套完整的设备树生成逻辑:
动态构建:每次启动时,QEMU 会根据
-m(内存)、-smp(CPU 核数)等参数,在内存中实时构建一个 DTB 结构,然后通过a1寄存器或 FDT 地址传递给内核/OpenSBI。无静态文件:它不像树莓派等真实硬件那样,有一个对应的
virt.dtb文件放在/boot或 QEMU 安装目录中。
📥 如何获取这个 DTB(导出为文件)
如果你需要查看或使用这个 DTB(例如用于内核调试、手动加载),可以使用 QEMU 的dumpdtb机器选项将其导出到当前目录:
# 使用 dumpdtb 参数导出,导出后 QEMU 会立即退出 qemu-system-riscv64 -machine virt,dumpdtb=riscv64-virt.dtb -bios default执行后,你会在当前目录下得到riscv64-virt.dtb文件。你可以使用dtc(Device Tree Compiler)工具将其反编译为可读的.dts文本格式:
dtc -I dtb -O dts riscv64-virt.dtb -o riscv64-virt.dts💡 开发建议
默认行为:在正常开发中,你不需要手动指定 DTB。QEMU 自动生成并传递的 DTB 是最准确的(包含你设定的确切内存布局)。
手动指定:只有当你需要强制使用 Linux 内核源码树中预定义的 DTB(如
qemu-riscv64-virt.dtb)时,才需要使用-dtb <file>参数,但这通常用于测试特定 DTS 修改,而非默认流程。
注:如果你在 Linux 源码树中看到了
arch/riscv/boot/dts/qemu/目录,那是 Linux 社区为了方便内核构建而维护的参考 DTS,并非 QEMU 运行时默认使用的那个二进制文件。
