Commit c486da26 authored by Felipe Borges's avatar Felipe Borges
Browse files

Disable creation of VMs with EFI firmware

Once upon a time we were very excited about introducing EFI support
in GNOME Boxes. It seemed like the right thing to do, there was a
vocal group of users requesting it.

Unfortunately, we were not aware at the time of the existing
limitations that it would introduce to our user experience. The most
critical one is undoubtedly support for snapshots.

Snapshots are one of the top selling features of GNOME Boxes. They
allow for reverting a virtual machine guest to a desired state in
time, including memory state. This is extremely useful for our users
that use VMs for system's development. Oftentimes they will perform
tasks which can leave their guests in a broken state, and snapshots
are here to save them.

Internal snapshots are really a migration to disk, this means that for
EFI you might end up trying to migrate to the backing store of the
nvram device. Therefore libvirt will scream:
"Operation not supported: internal snapshots of a VM with pflash based
firmware are not supported".

External snapshots can handle EFI. Except they don't. :) External
snapshots partially work for EFI guests. They can store the EFI state
in the memory image but we can't revert the guest to a given snapshot.

In the words of one of the libvirt developers "there was no time to
do it because of seemingly shinier features".

In my personal quest to workaround this issue, I attempted to use
internal snapshots storing DISK_ONLY content. No memory. That's
already a feature regression for us, but what can we do, right?
Everybody seems to want UEFI! It turns out that once you create an
internal snapshot with the DISK_ONLY flag, your snapshots become
external. So yep, no reverting.

All in all, I don't have a way to end this saga in a high note.
We are going to stop creating guests with EFI in the 3.36.x series,
and for 3.38 we will only create EFI guests for those operating
systems that libosinfo reports to support ONLY EFI. These guests
need EFI to boot, so in this case they won't have snapshots. For
the great majority of OSes that support BIOS, snapshots will
continue to exist and make our lives easier. The end.
Signed-off-by: Felipe Borges's avatarFelipe Borges <>
parent 2f6b8159
Pipeline #184936 failed with stages
in 2 minutes and 39 seconds
......@@ -29,8 +29,3 @@ option ('profile',
value: 'default'
option ('uefi',
type: 'boolean',
value: true,
description: 'Use UEFI whenever it is possible')
......@@ -55,20 +55,6 @@
public bool supports_efi {
get {
if (os == null)
return false;
foreach (var iter in os.get_firmware_list (null) .get_elements ()) {
var firmware = iter as Firmware;
if (firmware.get_firmware_type () == "efi")
return true;
return false;
public virtual bool prefers_q35 {
get {
if (os == null)
......@@ -194,9 +194,6 @@ else
dependencies += libovf.get_variable('govf_vapi')
if get_option('uefi')
vala_args += '--define=USE_UEFI'
executable ('gnome-boxes', vala_sources + resources,
include_directories: config_h_dir,
......@@ -38,7 +38,7 @@
private const string LIBOSINFO_XML = "<libosinfo>%s</libosinfo>";
private const string LIBOSINFO_OS_ID_XML = "<os id=\"%s\"/>";
public static Domain create_domain_config (InstallerMedia install_media, string target_path, Capabilities caps, DomainCapabilities domain_caps)
public static Domain create_domain_config (InstallerMedia install_media, string target_path, Capabilities caps)
throws VMConfiguratorError {
var domain = new Domain ();
......@@ -51,7 +51,7 @@ public static Domain create_domain_config (InstallerMedia install_media, string
var virt_type = guest_kvm_enabled (best_caps) ? DomainVirtType.KVM : DomainVirtType.QEMU;
domain.set_virt_type (virt_type);
set_os_config (domain, install_media, best_caps, domain_caps);
set_os_config (domain, install_media, best_caps);
string[] features = {};
if (guest_supports_feature (best_caps, "acpi"))
......@@ -375,45 +375,17 @@ private static void set_post_install_os_config (Domain domain) {
os.set_arch (old_os.get_arch ());
os.set_machine (old_os.get_machine ());
if (old_os.get_firmware () == GVirConfig.DomainOsFirmware.EFI)
os.set_firmware (GVirConfig.DomainOsFirmware.EFI);
domain.set_os (os);
private static bool domain_caps_supports_efi (DomainCapabilities domain_caps) {
foreach (var firmware in domain_caps.get_os ().get_firmwares()) {
if (firmware == GVirConfig.DomainOsFirmware.EFI)
return true;
return false;
private static bool supports_efi (InstallerMedia install_media, DomainCapabilities domain_caps) {
if (install_media == null || !install_media.supports_efi)
return false;
if (domain_caps == null || !domain_caps_supports_efi (domain_caps))
return false;
return true;
private static void set_os_config (Domain domain, InstallerMedia install_media, CapabilitiesGuest guest_caps, DomainCapabilities domain_caps) {
private static void set_os_config (Domain domain, InstallerMedia install_media, CapabilitiesGuest guest_caps) {
var os = new DomainOs ();
os.set_os_type (DomainOsType.HVM);
os.set_arch (guest_caps.get_arch ().get_name ());
if (install_media.prefers_q35)
os.set_machine ("q35");
if (supports_efi (install_media, domain_caps))
os.set_firmware (GVirConfig.DomainOsFirmware.EFI);
var boot_devices = new GLib.List<DomainOsBootDevice> ();
install_media.set_direct_boot_params (os);
boot_devices.append (DomainOsBootDevice.CDROM);
......@@ -192,8 +192,7 @@ protected void set_post_install_config (LibvirtMachine machine) {
StorageVol volume,
Cancellable? cancellable) throws GLib.Error {
var caps = yield connection.get_capabilities_async (cancellable);
var domcaps = yield connection.get_domain_capabilities_async (null, null, null, null, 0, cancellable);
var config = VMConfigurator.create_domain_config (install_media, volume.get_path (), caps, domcaps);
var config = VMConfigurator.create_domain_config (install_media, volume.get_path (), caps); = name;
config.title = title;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment