According to The OSDev Wiki “Any recent version of QEMU with a recent version of OVMF will be sufficient to run a UEFI application“. Nice. How do we set this up on a Windows host?
- Download a QEMU Windows build from https://qemu.weilnetz.de/w64/ (direct link to the latest version as of the writing of this: https://qemu.weilnetz.de/w64/2020/qemu-w64-setup-20200814.exe ) (Why does this page even have 32-bit builds? Is anyone in 2020 still using a 32-bit computer?)
- Install it
- Download the latest Open Virtual Machine Firmware x86-64 build (which is part of Tianocore EFI Development Kit 2) from https://www.kraxel.org/repos/jenkins/edk2/ (direct link to the latest version as of the writing of this: https://www.kraxel.org/repos/jenkins/edk2/edk2.git-ovmf-x64-0-20201023.1487.g2363c69260.noarch.rpm )
- Extract the .rpm using 7zip or some other archive opening tool.
- Make a batch file to test out QEMU + OVMF:
"c:\Program Files\qemu\qemu-system-x86_64.exe" -bios "C:\<path where you extracted the rpm>\usr\share\edk2.git\ovmf-x64\OVMF-pure-efi.fd"
- When you run it, you should get a message like “BdsDxe: failed to load Boot0001…” and it should eventually dump you into a UEFI shell. This means OVMF is running.
- Now modify the batch file to add a few flags. We need to listen on the default GDB port:
"c:\Program Files\qemu\qemu-system-x86_64.exe" -bios "C:\<path where you extracted the rpm>\usr\share\edk2.git\ovmf-x64\OVMF-pure-efi.fd" -s -S
- Now run it again. The UEFI bootloader shouldn’t run. QEMU is waiting for us to connect via GDB and tell it to start running.
- We’ll need a GDB that works on Windows. Codesourcery (now part of Mentor Graphics) has cross-compiler toolchains, including a “Linux” GDB that will run on Windows. https://www.mentor.com/embedded-software/toolchain-services/ (Direct link to the latest version as of the writing of this: https://sourcery.mentor.com/GNUToolchain/package14750/public/x86_64-amd-linux-gnu/amd-2016.11-19-x86_64-amd-linux-gnu.exe – later versions are source-only and don’t have builds(?!) )
- Let’s make another batch file to test running our newly-installed Windows-compiled GDB!:
- Run that, and you should get a GDB terminal.
- Type “
target remote tcp::1234“. GDB should complain that no executable has been specified, which verifies that it’s connected and found that to be true!
- Type “
continue“, and the UEFI bootloader should run!
- From here, it’ll be a good idea to create a kernel and try to add a breakpoint.
- Here’s a blog post on how to create a simple kernel that just prints “OK” to the console: https://os.phil-opp.com/multiboot-kernel/
- NASM Windows builds can be found here: https://www.nasm.us/pub/nasm/releasebuilds/
- Following the above blog post should be straightforward, but as a hint, here’s my batch file for creating the kernel.bin file:
"C:\Program Files\NASM\nasm.exe" multiboot_header.asm
"C:\Program Files\NASM\nasm.exe" boot.asm
"C:\Program Files\NASM\nasm.exe" -f elf64 boot.asm
"C:\Program Files\NASM\nasm.exe" -f elf64 multiboot_header.asm
"C:\mgc\embedded\codebench\bin\x86_64-amd-linux-gnu-ld.exe" -n -o kernel.bin -T linker.ld multiboot_header.o boot.o
- TODO: Probably want to backtrack here a bit and create an EFI executable instead. Probably using NASM, because GNU-EFI does too much of the work for us, and this is primarily a learning adventure for me.