Home > Linux, Server stuff > How to boot Windows partition virtually under KVM with UEFI firmware

How to boot Windows partition virtually under KVM with UEFI firmware

It is actually quite easy to boot Windows virtualized using KVM. But to properly use the UEFI bootloader, suitable QEMU arguments are required. Here is a lightly commented QEMU command I use to boot virtual Windows 10 I have on a separate partition.


sudo qemu-system-x86_64 --enable-kvm -cpu host -m 2048 -smp 3 -mem-path /dev/hugepages \
-display sdl -vga qxl \
-device qemu-xhci,id=xhci \
-device virtio-tablet,wheel-axis=true \
-soundhw hda \
-netdev user,id=vmnic,smb=/temp \
-device virtio-net,netdev=vmnic \
-drive file=/usr/share/ovmf/x64/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \
-drive file=$HOME/.config/qemu-windows.nvram,if=pflash,format=raw,unit=1 \
-drive file=/dev/sdb,index=0,media=disk,driver=raw \
-cdrom /opt/UefiShell.iso

For now I use sudo, because QEMU needs to access raw partitions from /dev/sdb. The other, better way would be assigning a group to /dev/sdb, setting up proper group permissions and adding me to that group.

-m 2048 -smp 3 says to allocate 2GB of RAM for the guest and use 3 CPU cores

-mem-path /dev/hugepages is better described in Arch wiki.

-display sdl -vga qxl Use SDL for rendering and window management in the host and QXL GPU device in the guest (there are QXL drivers for Windows).

-device qemu-xhci,id=xhci Enable USB3 support by emulating an XHCI controller

-device virtio-tablet,wheel-axis=true Emulate a tablet pointing device with mouse scroll support

-soundhw hda Emulate Intel HD Audio

netdev stuff Is for setting up network interface

-drive file=/usr/share/ovmf/x64/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on This is a very important part. It loads OVMF UEFI firmware read-only as the first Flash device. This firmware implements a UEFI bios and allows running UEFI Shell or booting .efi bootloader for Windows (bootmgfw.efi). This OVMF can be downloaded directly from the OVMF project repo or if you are using Arch Linux, just install ovmf package.

-drive file=$HOME/.config/qemu-windows.nvram,if=pflash,format=raw,unit=1 this loads a read-write NVRam flash image as the second virtual flash chip. OVMF firmware uses this to store UEFI variables, .efi boot order, etc. The default image can be copied from the OVMF setup (at /usr/share/ovmf/x64/OVMF_VARS.fd in ovmf Arch linux package). It must be a writable copy.

-drive file=/dev/sdb,index=0,media=disk,driver=raw Attaches my raw sdb block device to the virtual machine. That is used as a HDD for the guest, it has Windows pre-installed there together with EFI partition.

-cdrom /opt/UefiShell.iso UEFI shell iso as a CDROM. Before OVMF nvram is properly configured to boot Windows by default, this will result in booting into the EFI shell which allows to run .efi executables manually. Windows can be run by just navigating into the EFI partition and running the Windows efi loader – blkX:\EFI\Microsoft\Boot\bootmgfw.efi.

I don’t know how to force Windows to write UEFI boot order. There doesn’t seem to be a tool like efibootmgr on Windows. :D Windows would set the UEFI boot order up randomly during some Windows Updates (mostly when you don’t want it to touch your EFI setup). It eventually set the EFI config up for me itself quite quickly. But if it fails, you can try pressing ESC during TianoCore EFI boot to get to boot menu. Or you can always boot Linux using the -cdrom command and use efibootmgr to force the OVMF to boot the Windows loader entry for this virtual machine by default. Usage of the efibootmgr command is out of scope of this article and can be found in many online resources elsewhere.

Have fun with virtualized Windows and remember – Windows is good for games only and for stuff like government PDFs which use proprietary Adobe XFA forms and are therefore supported in official Adobe Reader which has the best support in this lousy platform only. Windows definitely shouldn’t be used on servers or anything serious! By default it is very limited (maximum number or RAM, maximum number of CPU cores, maximum number of listening socket connections, etc) until you pay huge amounts of money to Microsoft. Wise people use Linux and lazy people who don’t care about privacy or freedom use Mac OS X.

Categories: Linux, Server stuff Tags:
  1. defb
    August 1st, 2018 at 03:49 | #1

    I’m attempting to run this with debian testing (at the moment deb10), but unfortunately, the ovmf package in the deb repos don’t have /usr/share/ovmf/x64/OVMF_CODE.fd. Also, by OVMF_CODE.fd, do you mean copy it over to .config and renaming it qemu-windows.nvram? Other than that, I’m impressed at how you can virtualize a physical install of windows when virtual box has trouble doing it.

    • k3a
      August 1st, 2018 at 16:23 | #2

      For Debian (deb/apt) you can list the content of a package with
      # dpkg-query -L ovmf
      ...
      /usr/share/OVMF/OVMF_CODE.fd
      /usr/share/OVMF/OVMF_VARS.fd
      ...

      So just update the path.

      In my case qemu-windows.nvram is a “user” copy of OVMF_VARS.fd. It is mapped by QEMU as a second persistent flash (first being the actual UEFI bios binary which won’t change). This second flash (represented also as a file here) stores the bios settings – mainly boot order (the EFI boot order manages the OS like Windows or utility efibootmgr on Linux and BIOS stores it in this config flash). The original OVMF_VARS.fd contains the ‘default’ settings.

  2. Björn Carlsson
    August 6th, 2018 at 08:04 | #3

    Where did you find UefiShell.iso

  3. Ivan Avery Frey
    November 3rd, 2018 at 21:19 | #5

    Thank you for these instructions. My Linux install is on the same disk as my Windows install. Is there a way to boot Windows virtually when Linux and Windows are on the same physical device?

    • k3a
      November 3rd, 2018 at 21:32 | #6

      Hey. Definitely. Partitions are on different parts of the physical drive. And this is exactly what I am doing here. I mounted /dev/sdb with index 0 (which is equivalent to /dev/sdb1 where my EFI partition is and this /dev/sdb drive is where I have both OS installed. Note that QEMU counts from 0, Linux creates /dev/sdbX starting 1).

      My abbreviated output of fdisk -l /dev/sdb:

      /dev/sdb1 EFI System
      /dev/sdb2 AFS
      /dev/sdb3 Microsoft basic data
      /dev/sdb4 Microsoft reserved
      /dev/sdb5 Linux filesystem root
      /dev/sdb6 Linux filesystem swap

      The EFI partition (/dev/sdb1 in my case) is where the windows bootloader is (/EFI/Microsoft/Boot/bootmgfw.efi). EFI implementation (or EFI console) can then run this bootloader which then loads registry-like /EFI/Microsoft/Boot/BCD file where the partition UUID of the Windows installation is. That Windows bootloader would then load that partition and continue normal windows booting. So you will use EFI partition initially, run Windows bootloader on it (you can use EFI console mounted as cdrom at the beginning or use boot options of the TianoCore EFI firmware – hit ESC during boot), which then finds and loads the the big windows partition, mounts it and boots from it.

  4. rp
    December 14th, 2018 at 22:31 | #7

    Thank you very much for these instructions. I was able to boot up my windows partition. However I only get a 800×600 resolution. I suspect it must be something to do with the fact that I don’t have virtio drivers installed in my windows guest. I am not clear how to go about doing this and more specifically what drivers to install from the fedora repository. Could you please give some additional details on virtio driver installation in the windows guest?

  5. k3a
    December 15th, 2018 at 08:55 | #8

    @rp
    You can extract them from Fedora distribution. Fedora ships these drivers signed so they will install without any hacks. I don’t remember exact place but I think I extracted them from rpm – here is a list of fedora stable rpms https://fedorapeople.org/groups/virt/virtio-win/repo/stable/ . Ubuntu also ships the drivers but I don’t know if they are signed. Their debs are here https://launchpad.net/kvm-guest-drivers-windows/+download.

  1. No trackbacks yet.