[vfio-users] Windows 7 successfully migrated from BIOS to OVMF/UEFI

Leonhard Preis leonhard at pre.is
Mon May 16 09:20:30 UTC 2016


My dear fellow vfio users,

today I want to share my success[1] with you. In case you have Windows 7  
and currently use BIOS but would like to switch to UEFI or are about to  
set up your first Windows VM with passthrough and would prefer Windows 7  
over Windows 8 and above, rejoice: It’s working just fine.

Important specs:
================

```
System:    Kernel: 4.5.2-1-vfio x86_64 (64 bit) Distro: Arch Linux
Machine:   Mobo: ASRock model: Z87 Extreme6 Bios: American Megatrends v:  
P2.40 date: 07/08/2014
CPU:       Quad core Intel Core i7-4771 (-HT-MCP-) speed/max: 3802/3900 MHz
Graphics:  Card-1: Intel Xeon E3-1200 v3/4th Gen Core Processor Integrated  
Graphics Controller
            Card-2: Advanced Micro Devices [AMD/ATI] Hawaii XT [Radeon R9  
290X]
Source: inxi

qemu: 2.5.1-1
ovmf-git: 18487.c4cc609-1
```
[8][9]
I haven’t switched to Arch’s “normal” kernel yet and probably will use a  
self-compiled version anyway since I went through the pains of tailoring  
the kernel config to my machine. This should not make a difference though.
As if switching from BIOS to UEFI wasn’t enough I also migrated from a  
script based on nbhs’ original work to libvirt at the same time -  
apologies if some things seem redundant or obvious to you.


Graphics card firmware and UEFI
===============================

This brings me to the first obstacle I encountered: Your graphics card’s  
bios/firmware needs to support UEFI, too. To my complete surprise and only  
after hours of tinkering I found out that my Sapphire R9 290X Tri-X OC  
does *not* support UEFI, at least not the version[2] I have. Luckily  
there’s an UEFI-enabled firmware version[3] for this very same card which  
works perfectly - for me. Be advised that I read posts that some cards may  
fail to work with it and in fact may be bricked if you flash this version,  
voiding your warranty. If you still do it it’s of course at your own risk  
- I’m just sharing my story :-).

Since I’m a cautious man I checked the existing firmware before flashing.  
I managed to drop the first 64 KiB by running:

```shell
# echo 1 > /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rom
# cat /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rom >~/firmware.bin
# echo 0 > /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rom
```

Opening it with Vim gives you a lot of binary garbage but luckily all the  
interesting information is there in ASCII, esp. the device ID (GPU Device  
Id: `0x1002 0x67B0 113-C6710100-O05`) and current firmware version  
(`ATOMBIOSBK-AMD VER015.042.000.000.000000 285X0500.O45`). After flashing  
the UEFI-enabled version[3] (the last three characters of the version and  
device ID differ) with atiflash[3] via FreeDOS[4] I had no more trouble  
with the graphics card.


Graphics and Video devices
==========================
Or at least not in a way that is necessarily up to the card. After some  
experimentation and some follow-up googling I found out that the Windows  
DVD does not work with my graphics card but needs the graphics and video  
devices emulated by Qemu - QXL and Spice in my case. Thank to whoever  
wrote this in the Debian Wiki page[6] on the subject.


Backups
=======
Fortunately I have plenty of room to store a backup of my system disk on  
my server, using `dd` and piping over `ssh`. If you decide to do that,  
too, you can make sure you have the exact same data on both ends by  
running `sha1sum` (or something similar) over the files/partitions, e.g.  
`# sha1sum /dev/vg-win/winsys`. Don’t forget to shut down your VM first.  
;-)
This also means you can selectively restore parts of the virtual disk,  
like the MBR and the first partition, e.g. like this (first 101 MiB):
```shell
sudo -u youruser ssh backup-host sudo dd  
if=/dev/vg-bak/winsys_bak_20160430 bs=1M count=101 | dd of=/dev/vg-win/win  
iflag=fullblock
```


The Conversion from BIOS to UEFI
================================
Luckily, there’s an semi-official guide[7] on Microsoft’s TechNet  
explaining the procedure which is almost accurate. Please take note that  
you first need to boot into your VM using the BIOS emulation to convert  
*all* your volumes to GPT if they use MBR. I have been told that for  
Windows 7 to be able to use UEFI, all disks need to use GPT. I tried using  
gdisk to do a conversion in Linux instead of the tool recommended by the  
guide but this was probably the reason why the repair routine missed the  
installed Windows. It also could have been a fuckup on my behalf so try it  
out yourself!
Also my machine did *not* die on me with a BSoD, I just shut it down  
normally. Since I performed the procedure twice (backups, backups,  
backups!) I can say with certainty that a BSoD is not a given.

After you shut down your machine, you have to change your configuration to  
use UEFI instead of BIOS. Since I experimented a lot and only migrated to  
libvirt during this procedure I got my UEFI-vars created automatically  
when I created the configuration via virt-manager. Beforehand I had  
configured libvirt to offer UEFI-support[11]. Since you need to boot using  
BIOS first and only switch to UEFI after the MBR-to-GPT conversion, I  
simply removed the `<loader>` and `<nvram>` lines and added them back in  
afterwards.
```xml
   <os>
     <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type>
     <loader readonly='yes'  
type='pflash'>/usr/share/ovmf/x64/ovmf_code_x64.bin</loader>
     <nvram>/var/lib/libvirt/qemu/nvram/win7_VARS.fd</nvram>
   </os>
```
You can find some information on this in Alex’ post[1].

The recovery CD booted using the QXL/Spice display while the “real”  
Windows installation always uses my physical graphics adapter. Maybe you  
can remove these once you do not need the recovery CD anymore - I have not  
tried it yet.


Where the guide didn’t fit
--------------------------

1. After booting the VM you of course need to first load the virtio  
drivers from a second virtual DVD drive but that shouldn’t surprise you if  
you use virtio.
2. I had already removed my Windows boot partition (the one which has  
about 200 MiB) at some earlier date, leaving me with a single system  
partition and, looking back, luckily with a 101 MiB of space in front of  
it. So I did *not* have to delete some existing partitions, just create a  
single new one.
3. My first irritation was when I issued `create partition EFI size=100  
offset=1` and it returned some error about some invalid operation telling  
me to look into the system protocol. Basically I didn’t care about it once  
I found out that the partition was created and a protected `System`  
partition - but only after a reboot. I guess the kernel simply couldn’t  
reload the partition table after the change.
4. You can imagine my reaction when I found out that *the* parameter the  
guide uses, `/f UEFI`, does not exist in the version of bcdboot Windows 7  
ships. This is in accordance with the official documentation[10]. Luckily,  
as it turns out, Windows automatically selects the appropriate format  
based on the way you booted the image, BIOS or UEFI. Just use `bcdboot  
c:\windows /s s:` without `/f UEFI`. But this actually gave me an error  
too. Which brings me to
5. After creating the UEFI partition and rebooting for it to be recognized  
by the recovery environment, Windows offered me to automatically repair  
the start up once I loaded the virtio drivers. I accepted and can confirm  
it worked. If you want to be 100% sure it’s done right you can deny the  
offer, open `diskpart` and make sure the proper drive letters are assigned  
as outlined by the guide[7]. Once you exited `diskpart` you can manually  
launch the automatic startup repair tool.


**That should be it.**

Maybe I forgot some detail, I have spent a couple of days spread over two  
weeks on this, mostly figuring out that something doesn’t work and often  
why. I hope to find the time to update the Arch Linux wiki[11] with some  
of my findings some time soon, I think Nicolas did some great work there  
already.


A little rant
=============
Alex’ blog post[12] unsettled me quite a bit when I started my  
preparations:

> A gaming platform is often the target for "enthusiast" use of GPU  
> assignment, so Windows 8/8.1 is probably a good target if you can bear  
> the user interface long enough to start a game.  AFAIK, Windows 7 does  
> not support UEFI natively, requiring the CSM (Compatibility Support  
> Module) which I believe defeats the purpose of using UEFI.  If one of  
> these guests does not meet your needs, turn away now.

I’m glad to report that he’s mistaken. As are the people who claimed on  
some forums that you cannot convert an existing instance which uses BIOS  
with OVMF. This is not meant as an insult just a note of caution to all to  
not let such claims stop you from trying and a request to you, Alex, to  
add a note to your blog post. There may be other people like me who do not  
like to run any Windows version above 7 even if it’s “just” virtual. After  
all we all know the actual IOMMU implementations are not always as secure  
as the idea may suggest. And even if …

Cheers,
Leonhard

PS: If you think that the screenshot is composed you are completely right.  
The reason is that I’m using Synergy and somehow using the “Print Screen”  
key is always interpreted as Alt+Print meaning only the currently focussed  
window is being “photographed”.

[1] https://www.anony.ws/image/JQRe
[2] http://www.techpowerup.com/vgabios/151536/sapphire-r9290x-4096-131212
[3] http://www.techpowerup.com/vgabios/151774/sapphire-r9290x-4096-131212-1
[4] http://www.techpowerup.com/downloads/2306/atiflash-4-17
[5] http://chtaube.eu/computers/freedos/bootable-usb/
[6] https://wiki.debian.org/VGAPassthrough#Guest_OS_Installation
[7]  
http://social.technet.microsoft.com/wiki/contents/articles/14286.converting-windows-bios-installation-to-uefi.aspx
[8] https://aur.archlinux.org/packages/ovmf-git/
[9] https://aur.archlinux.org/packages/linux-vfio/
[10] https://technet.microsoft.com/en-gb/library/dd744347(v=ws.10).aspx
[11]  
https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF#Configuring_libvirt
[12]  
http://vfio.blogspot.co.at/2014/08/primary-graphics-assignment-without-vga.html

-- 
Mit freundlichen Grüßen // Avec mes meilleures salutations // Best Regards
Leonhard Preis




More information about the vfio-users mailing list