tangptr@126.com 发表于 2023-9-23 09:58:16

【UEFI】一种快速测试运行EFI程序的方法


# 前言
很久之前发过我关于对UEFI开发的探索。我那个时候的方法是把EFI文件拷进U盘,再直通进虚拟机里,或者插到哪台真机上。这个操作实际上太繁琐了,只有真机运行才是其优势。

# 正文
其实作为虚拟机,用虚拟磁盘映像才是最便捷的方案。当时我没有快速制作虚拟磁盘映像的这个概念,导致开发EFI程序都得插着U盘,非常折腾。
最近才发现制作一个虚拟磁盘其实挺简单的。

## 在Linux环境制作映像
先说Linux环境,因为我发现的这个方案是基于Linux的。
方法是安装`mtools`包,以Ubuntu/Debian发行版的Linux为例:
```
sudo apt install mtools
```
毕竟不涉及内核操作,仅仅是编辑文件什么的。所以这套东西在WSL上(不论WSL1还是WSL2)也是可以用的。

然后是创建空的虚拟磁盘映像,命名为`disk.img`。
```
dd if=/dev/zero of=disk.img bs=1k count=1440
```
接着将其格式化,并创建EFI需要的目录
```
mformat -i disk.img -f 1440 ::
mmd -i disk.img ::/EFI
mmd -i disk.img ::/EFI/BOOT
```
最后是复制粘贴到这个虚拟磁盘了
```
mcopy -i disk.img bootx64.efi ::/EFI/BOOT
```
如果需要别的文件,可以追加`mcopy`命令。
把这些东西放进Makefile或者啥编译脚本里,就能直接生成一个包含EFI程序的虚拟磁盘映像了。

## 在Windows环境制作映像
如果你的系统能使用WSL,那可以直接照搬Linux环境里的操作。这里说的是不借助WSL的方案。(比如Windows 7不能使用WSL)

首先是创建空文件,Windows里可以用`fsutil`命令创建指定大小的空文件。
```
fsutil file createNew disk.img 1474560
```
注意`fsutil`只接受字节这个单位。

接着就是`mtools`这套东西了。网上没有找到直接发布EXE的,不知道为啥。但是能[下载到源码](https://www.gnu.org/software/mtools/)。但是不知道为啥,又找不到mtools的官方git repo,只能下载tar.gz压缩包。
总之只能自己编译了。这里踩了不少坑。我下载到的版本是4.0.43版的。
既然作为GNU的玩意,最省事的解决方案就是通过GCC来编译了。在Windows上安装(https://www.msys2.org/)来获取GCC。
我们使用MinGW64的控制台,首先先更新一下。注意msys2的控制台要用Shift+Ins键来粘贴,不能用Ctrl+V。
```
pacman -Syu --noconfirm
```
控制台在更新完毕后关闭。重启它,更新剩余的东西
```
pacman -Su
```
我并不知道`mtools`具体依赖了哪些包裹。我安装`msys2`是为了编译QEMU的,所以安装了以下内容:
```
pacman -S base-devel mingw-w64-x86_64-toolchain git python ninja
pacman -S mingw-w64-x86_64-glib2 mingw-w64-x86_64-pixman python-setuptools
pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-SDL2 mingw-w64-x86_64-libslirp
```
我估计其实安装第一行的`base-devel`和`mingw-w64-x86_64-toolchain`这两样就够了。
然后用`cd`命令切换到`mtools`的源码目录里。比方说你把源码放进了`D:\mtools-src`目录的话,就用`cd /d/mtools-src/`命令。
然后是进行配置。
```
./configure
```
配置完成后,别急着编译,mtools源码(4.0.43版)在Windows上编译是有坑的,要先改一下`config.h`文件。
找到`#define HAVE_ICONV_H 1`这一行,把它注释掉。
找到`/* #undef HAVE_LIBICONV */`这一行,取消其注释。
最后编译之。
```
make -j$(nproc)
```
最后把生成出来的这些exe文件复制到`PATH`环境变量里能找到的地方。
```
cp *.exe 目标路径
```
这下就能用`mtools`来制作映像了。直接照搬前面在Linux上说的,用`mformat`,`mmd`和`mcopy`这些命令即可。

## 运行UEFI映像
先说说VMware Workstation上的运行方法。
在VMware里,raw格式的磁盘映像可以视为软盘映像。因此直接向虚拟机添加软盘即可。
然后在固件设置里,直接运行`EFI Floppy`选项即可。
可以在固件设置里调整优先级来让虚拟机开机就运行你的EFI程序。

另一种方案是用QEMU。如果用惯了命令行,或许QEMU会更简单。
注意QEMU默认使用SeaBIOS作为固件,它是Legacy的。因此要下载TianoCore的OVMF固件才能运行EFI程序。
在Linux里很简单,直接用安装命令即可一次性安装QEMU和OVMF。
```
sudo apt install qemu-system ovmf
```
但在Windows里,还得找别的办法来用OVMF。
Kraxel发布过[编译好的OVMF固件](https://www.kraxel.org/repos/jenkins/edk2/),可以直接下载。
虽然不是最新版的(Kraxel不再更新编译好的OVMF了),但是能用就行。如果有所追求,那就直接下载源码自己编译OVMF吧。
Kraxel发布的是RPM包,这个文件可以直接用7z打开。提取出里面的`OVMF-pure-efi.fd`文件,这就是我们要用的OVMF固件。为了和Linux使用一样的命令,建议将其重命名为OVMF.fd。
接着就是运行QEMU了,代码很简单,指定一下用哪个固件,以及加上哪个磁盘映像即可。
```
qemu-system-x86_64 -bios OVMF.fd -drive format=raw,file=disk.img
```
有什么别的需求可以追加参数。

# 结语
本文介绍了一种快速测试EFI程序的方案。简单说就是怎么把EFI程序包装成一个虚拟磁盘映像。
这里用到了`mtools`包,在Linux里可以直接安装,但在Windows里就需要自己编译了。
最后分别说明了如何用VMware和QEMU运行你的EFI程序。注意QEMU需要额外下载OVMF固件来运行EFI程序。
页: [1]
查看完整版本: 【UEFI】一种快速测试运行EFI程序的方法