Early notes on switching some libvirt-based virtual machines to UEFI
I keep around a small collection of virtual machines so I don't have to drag out one of our spare physical servers to test things on. These virtual machines have traditionally used traditional MBR-based booting ('BIOS' in libvirt instead of 'UEFI'), partly because for a long time libvirt didn't support snapshots of UEFI based virtual machines and snapshots are very important for my use of these scratch virtual machines. However, I recently discovered that libvirt now can do snapshots of UEFI based virtual machines, and also all of our physical server installs are UEFI based, so in the past couple of days I've experimented with moving some of my Ubuntu scratch VMs from BIOS to UEFI.
As far as I know, virt-manager and virsh don't directly allow you to switch a virtual machine between BIOS and UEFI after it's been created, partly because the result is probably not going to boot (unless you deliberately set up the OS inside the VM with both an EFI boot and a BIOS MBR boot environment). Within virt-manager, you can only select BIOS or UEFI at setup time, so you have to destroy your virtual machine and recreate it. This works, but it's a bit annoying.
(On the other hand, if you've had some virtual machines sitting around for years and years, you might want to refresh all of their settings anyway.)
It's possible to change between BIOS and UEFI by directly editing
the libvirt XML to transform the <os> node.
You may want to remove any old snapshots first because I don't know
what happens if you revert from a 'changed to UEFI' machine to a
snapshot where your virtual machine was a BIOS one. In my view, the
easiest way to get the necessary XML is to create (or recreate)
another virtual machine with UEFI, and then dump and copy its XML
with some minor alterations.
For me, on Fedora with the latest libvirt and company, the <os> XML of a BIOS booting machine is:
<os> <type arch='x86_64' machine='pc-q35-6.1'>hvm</type> </os>
Here the 'machine=' is the machine type I picked, which I believe is the better of the two options virt-manager gives me.
My UEFI based machines look like this:
<os firmware='efi'>
<type arch='x86_64' machine='pc-q35-9.2'>hvm</type>
<firmware>
<feature enabled='yes' name='enrolled-keys'/>
<feature enabled='yes' name='secure-boot'/>
</firmware>
<loader readonly='yes' secure='yes' type='pflash' format='qcow2'>/usr/share/edk2/ovmf/OVMF_CODE_4M.secboot.qcow2</loader>
<nvram template='/usr/share/edk2/ovmf/OVMF_VARS_4M.secboot.qcow2' templateFormat='qcow2' format='qcow2'>/var/lib/libvirt/qemu/nvram/[machine name]_VARS.qcow2</nvram>
</os>
Here the '[machine-name]' bit is the libvirt name of my virtual machine, such as 'vmguest1'. This nvram file doesn't have to exist in advance; libvirt will create it the first time you start up the virtual machine. I believe it's used to provide snapshots of the UEFI variables and so on to go with snapshots of your physical disks and snapshots of the virtual machine configuration.
(This feature may have landed in libvirt 10.10.0, if I'm reading release notes correctly. Certainly reading the release notes suggests that I don't want to use anything before then with UEFI snapshots.)
Manually changing the XML on one of my scratch machines has worked fine to switch it from BIOS MBR to UEFI booting as far as I can tell, but I carefully cleared all of its disk state and removed all of its snapshots before I tried this. I suspect that I could switch it back to BIOS if I wanted to. Over time, I'll probably change over all of my as yet unchanged scratch virtual machines to UEFI through direct XML editing, because it's the less annoying approach for me. Now that I've looked this up, I'll probably do it through 'virsh edit ...' rather than virt-manager, because that way I get my real editor.
(This is the kind of entry I write for my future use because I don't want to have to re-derive this stuff.)
PS: Much of this comes from this question and answers.