[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