OVMF is a port of Intel's tianocore firmware to the qemu virtual machine. This allows easy debugging and experimentation with UEFI firmware; either for testing Ubuntu or using the (included) EFI shell.

Quick Start using virt-manager

  1. sudo apt-get install virt-manager libvirt-daemon ovmf
  2. Start creating a new VM in virt-manager, but before finishing, click "Customize configuration before install"
  3. Change the Firmware Option from BIOS to UEFI. (If it's not available do a systemctl restart libvirtd)
  4. Do whatever normal VM things you want to do. Initial screen when booting should now show TianoCore.


This is less necessary as the ovmf is now a package you can just apt get.

If you'd like to build your own image, follow the instructions at UEFI/EDK2. This will create the file Build/OvmfX64/DEBUG_GCC46/FV/OVMF.fd, which is the actual firmware image that qemu will use. Simple copy this to a file called bios.bin in the current directory.

Basic Qemu usage

For the simplest use-case, you can boot the machine like this (with bios.bin in the current directory):

qemu-system-x86_64 -L .

The -L . option tells qemu to look in the current directory for the bios.bin firmware image.

This will allow you to play with the firmware setup screens, and the EFI shell. However, there are no virtual disks available, so you won't be able to boot anything.

UEFI shell running on QEMU

Running an Ubuntu ISO

We can use the -cdrom argument to qemu to specify the Ubuntu installer ISO as a virtual CDROM. In this case, we also need to tell qemu that we want a little more memory (1024MB) than the default (128MB):

qemu-system-x86_64 -L . -cdrom ubuntu-12.04-desktop-amd64.iso -m 1024

Performing an install

If you'd like to run the Ubuntu installer and perform an actual install within the virtual machine, you'll need some virtual disk to install to. In this case, we'll create a 10GB file to act as the virtual disk:

truncate -s 10G ovmf.disk2

Then we can tell qemu to use this file as a virtual disk:

qemu-system-x86_64 -L . -cdrom ubuntu-12.04-desktop-amd64.iso -hda ovmf.disk -m 1024

If you prefer, you can use a block device as the qemu disk; just specify the device path instead of the file name (eg, -hda /dev/sdd). You'll probably need to run qemu with sudo for this to work.

Other usage

Some other options that may be helpful:

  • -enable-kvm: Use the KVM virtualisation support for better virtual machine performance. Requires root.

  • -serial pty: Allocate a PTY, and create a virtual serial device attached to the PTY. On startup, qemu will print the name of the PTY that is has allocated, and you can interact with it using screen /dev/pts/XX

  • -monitor stdio: Start the qemu monitor from the qemu prompt. This allows you to control the virtual machine from the terminal.

  • -nographic: Don't create a video device for the VM.

  • -S: Don't start the VM immediately

  • -hda fat:<directory>: Make <directory> available to the VM as a virtual FAT-formatted disk

This is how I generally use qemu for debugging:

sudo qemu-system-x86_64 -L . -serial pty -serial pty -monitor stdio \
        -drive file=/dev/local/virt-ovmf,if=ide,id=drive-ide0-0-0 \
        -nographic -S

This command:

  • Creates two serial ports: one for the OVMF debug output, and one for a usable serial console
  • Uses a LVM block device, /dev/local/virt-ovmf as the local storage

  • Disables graphic output
  • Starts the qemu monitor prompt on stdio
  • Tells qemu not to start the machine right away.

I then:

  • start two screen sessions on the PTYs that qemu prints
  • start it by typing c at the monitor prompt

During boot, I get the OVMF debug output on the first screen session, and once the machine is booted, I get a login prompt on the second screen session. For this to work, you'll need to configure init to create a getty session on the serial ports. To do this from within your virtual machine:

cd /etc/init/
sed s/tty1/ttyS0 < tty1.conf | sudo dd of=ttyS0.conf
sed s/tty1/ttyS1 < tty1.conf | sudo dd of=ttyS1.conf

UEFI/OVMF (last edited 2023-12-23 19:00:16 by dannf)