virtinst/guest: use EFI firmware if osinfo-db shows lack of BIOS support

Windows 11 only supports EFI for installation, legacy BIOS is
discontinued as an option for new installs, unless you switch into
the console and run various regedit hacks in the installer.

This is not something we expect users to do, so osinfo-db will
report:

   <firmware arch="x86_64" type="efi"/>
   <firmware arch="x86_64" type="bios" supported="false"/>

for Windows 11.

When seeing 'bios' with supported=false, we need to prefer EFI
firmware no matter what.

For other OS we should stil prefer BIOS, because EFI blocks the usage of
internal qcow2 snapshots until some libvirt work is done to use the new
QMP snapshot commands.

Note this relies on a new API osinfo_os_get_complete_firmware_list
just added to libosinfo in version 1.10, so for most existing OS
distros this will be dormant functionality until they rebase to
latest libosinfo APIs.

The Windows 11 entry for osinfo-db will be the first that exposes
the metadata indicating lack of BIOS support.

Related: https://github.com/virt-manager/virt-manager/issues/310
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2021-11-23 18:52:44 +00:00 committed by Cole Robinson
parent 9db16377e8
commit 5d74ca7621
2 changed files with 37 additions and 1 deletions

View File

@ -522,7 +522,21 @@ class Guest(XMLBuilder):
arm+machvirt prefers UEFI since it's required for traditional arm+machvirt prefers UEFI since it's required for traditional
install methods install methods
""" """
return self.os.is_arm_machvirt() or self.conn.is_bhyve() if self.os.is_x86() and self.conn.is_qemu():
# If OS has dropped support for 'bios', we have no
# choice but to use EFI.
# For other OS still prefer BIOS since it is faster
# and doesn't break QEMU internal snapshots
has_efi = self.osinfo.supports_firmware_efi(self.os.arch)
has_bios = self.osinfo.supports_firmware_bios(self.os.arch)
log.debug("Guest osinfo firmware has_efi=%d has_bios=%d",
has_efi, has_bios)
prefer_efi = has_efi and not has_bios
else:
prefer_efi = self.os.is_arm_machvirt() or self.conn.is_bhyve()
log.debug("Prefer EFI => %s", prefer_efi)
return prefer_efi
def is_uefi(self): def is_uefi(self):
if self.os.loader and self.os.loader_type == "pflash": if self.os.loader and self.os.loader_type == "pflash":

View File

@ -439,6 +439,28 @@ class _OsVariant(object):
devids = ["http://qemu.org/chipset/x86/q35"] devids = ["http://qemu.org/chipset/x86/q35"]
return bool(self._device_filter(devids=devids, extra_devs=extra_devs)) return bool(self._device_filter(devids=devids, extra_devs=extra_devs))
def _get_firmware_list(self):
if hasattr(self._os, "get_complete_firmware_list"):
return self._os.get_complete_firmware_list().get_elements()
return []
def _supports_firmware_type(self, name, arch, default):
firmwares = self._get_firmware_list()
for firmware in firmwares:
if firmware.get_architecture() != arch:
continue
if firmware.get_firmware_type() == name:
return firmware.is_supported()
return default
def supports_firmware_efi(self, arch):
return self._supports_firmware_type("efi", arch, False)
def supports_firmware_bios(self, arch):
return self._supports_firmware_type("bios", arch, True)
def get_recommended_resources(self): def get_recommended_resources(self):
minimum = self._os.get_minimum_resources() minimum = self._os.get_minimum_resources()
recommended = self._os.get_recommended_resources() recommended = self._os.get_recommended_resources()