]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Move firmware selection from startup to postparse
authorAndrea Bolognani <abologna@redhat.com>
Tue, 24 Jan 2023 16:01:48 +0000 (17:01 +0100)
committerAndrea Bolognani <abologna@redhat.com>
Fri, 3 Mar 2023 12:49:56 +0000 (13:49 +0100)
Currently, firmware selection is performed as part of the
domain startup process. This mostly works fine, but there's a
significant downside to this approach: since the process is
affected by factors outside of libvirt's control, specifically
the contents of the various JSON firmware descriptors and
their names, it's pretty much impossible to guarantee that the
outcome is always going to be the same. It would only take an
edk2 update, or a change made by the local admin, to render a
domain unbootable or downgrade its boot security.

To avoid this, move firmware selection to the postparse phase.
This way it will only be performed once, when the domain is
first defined; subsequent boots will not need to go through
the process again, as all the paths that were picked during
firmware selection are recorded in the domain XML.

Care is taken to ensure that existing domains are handled
correctly, even if their firmware configuration can't be
successfully resolved. Failure to complete the firmware
selection process is only considered fatal when defining a
new domain; in all other cases the error will be reported
during startup, as is already the case today.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
31 files changed:
src/qemu/qemu_domain.c
src/qemu/qemu_driver.c
src/qemu/qemu_firmware.c
src/qemu/qemu_firmware.h
src/qemu/qemu_process.c
tests/qemuxml2xmloutdata/aarch64-virt-graphics.aarch64-latest.xml
tests/qemuxml2xmloutdata/aarch64-virt-headless.aarch64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-bios-stateless.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-bios.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-aarch64.aarch64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-enrolled-keys.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-loader-secure.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-no-enrolled-keys.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-no-secboot.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-nvram-file.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-nvram-network-iscsi.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-nvram-network-nbd.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-nvram.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-secboot.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-smm-off.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi-stateless.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-auto-efi.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi-acpi-aarch64.aarch64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi-acpi-q35.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi-noacpi-aarch64.aarch64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi-nvram-file.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi-secure.x86_64-latest.xml
tests/qemuxml2xmloutdata/firmware-manual-efi.x86_64-latest.xml
tests/qemuxml2xmloutdata/pvpanic-pci-aarch64.aarch64-latest.xml
tests/qemuxml2xmloutdata/pvpanic-pci-no-address-aarch64.aarch64-latest.xml
tests/qemuxml2xmloutdata/virtio-iommu-aarch64.aarch64-latest.xml

index 9cba02dc5a6b1cc2082da4b0072ea5c905ec6916..f4ed5ffaebaaecc26087485dfa68cda6132f415f 100644 (file)
@@ -27,6 +27,7 @@
 #include "qemu_cgroup.h"
 #include "qemu_command.h"
 #include "qemu_capabilities.h"
+#include "qemu_firmware.h"
 #include "qemu_hostdev.h"
 #include "qemu_migration_params.h"
 #include "qemu_security.h"
@@ -4427,21 +4428,42 @@ qemuDomainRecheckInternalPaths(virDomainDef *def,
 
 static int
 qemuDomainDefBootPostParse(virDomainDef *def,
-                           virQEMUDriverConfig *cfg)
+                           virQEMUDriver *driver,
+                           unsigned int parseFlags)
 {
+    bool abiUpdate = !!(parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE);
+
     if (def->os.bootloader || def->os.bootloaderArgs) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("bootloader is not supported by QEMU"));
         return -1;
     }
 
-    if (virDomainDefHasOldStyleROUEFI(def) &&
-        !def->os.loader->nvram &&
-        def->os.loader->stateless != VIR_TRISTATE_BOOL_YES) {
-        def->os.loader->nvram = virStorageSourceNew();
-        def->os.loader->nvram->type = VIR_STORAGE_TYPE_FILE;
-        def->os.loader->nvram->format = VIR_STORAGE_FILE_RAW;
-        qemuDomainNVRAMPathFormat(cfg, def, &def->os.loader->nvram->path);
+    /* Firmware selection can fail for a number of reasons, but the
+     * most likely one is that the requested configuration contains
+     * mistakes or includes constraints that are impossible to
+     * satisfy on the current system.
+     *
+     * If that happens, we have to react differently based on the
+     * situation: if we're defining a new domain or updating its ABI,
+     * we should let the user know immediately so that they can
+     * change the requested configuration, hopefully into one that we
+     * can work with; if we're loading the configuration of an
+     * existing domain from disk, however, we absolutely cannot error
+     * out here, or the domain will disappear.
+     *
+     * To handle the second case gracefully, we clear any reported
+     * errors and continue as if nothing had happened. When it's time
+     * to start the domain, qemuFirmwareFillDomain() will be run
+     * again, fail in the same way, and at that point we'll have a
+     * chance to inform the user of any issues */
+    if (qemuFirmwareFillDomain(driver, def) < 0) {
+        if (abiUpdate) {
+            return -1;
+        } else {
+            virResetLastError();
+            return 0;
+        }
     }
 
     return 0;
@@ -4818,7 +4840,7 @@ qemuDomainDefPostParse(virDomainDef *def,
     if (qemuDomainDefMachinePostParse(def, qemuCaps) < 0)
         return -1;
 
-    if (qemuDomainDefBootPostParse(def, cfg) < 0)
+    if (qemuDomainDefBootPostParse(def, driver, parseFlags) < 0)
         return -1;
 
     if (qemuDomainDefAddDefaultDevices(driver, def, qemuCaps) < 0)
index d00eb1796f760360297e07910c3434e6538dd090..3f353eadfa9cbc0023ff070d7d7fcee88065e6b3 100644 (file)
@@ -6646,8 +6646,6 @@ qemuDomainUndefineFlags(virDomainPtr dom,
     if (vm->def->os.loader && vm->def->os.loader->nvram &&
         virStorageSourceIsLocalStorage(vm->def->os.loader->nvram)) {
         nvram_path = g_strdup(vm->def->os.loader->nvram->path);
-    } else if (vm->def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_EFI) {
-        qemuDomainNVRAMPathFormat(cfg, vm->def, &nvram_path);
     }
 
     if (nvram_path && virFileExists(nvram_path)) {
index 72036bd82be211a734c1b1a50e6422992f443956..4a6adedfcb1b5f3156296f10220aad0e033180f2 100644 (file)
@@ -26,6 +26,7 @@
 #include "qemu_capabilities.h"
 #include "qemu_domain.h"
 #include "qemu_process.h"
+#include "domain_validate.h"
 #include "virarch.h"
 #include "virjson.h"
 #include "virlog.h"
@@ -1176,11 +1177,10 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
 
 
 static int
-qemuFirmwareEnableFeatures(virQEMUDriver *driver,
-                           virDomainDef *def,
-                           const qemuFirmware *fw)
+qemuFirmwareEnableFeaturesModern(virQEMUDriverConfig *cfg,
+                                 virDomainDef *def,
+                                 const qemuFirmware *fw)
 {
-    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
     const qemuFirmwareMappingFlash *flash = &fw->mapping.data.flash;
     const qemuFirmwareMappingKernel *kernel = &fw->mapping.data.kernel;
     const qemuFirmwareMappingMemory *memory = &fw->mapping.data.memory;
@@ -1216,10 +1216,8 @@ qemuFirmwareEnableFeatures(virQEMUDriver *driver,
             }
         }
 
-        VIR_DEBUG("decided on firmware '%s' template '%s' NVRAM '%s'",
-                  loader->path,
-                  NULLSTR(loader->nvramTemplate),
-                  NULLSTR(loader->nvram ? loader->nvram->path : NULL));
+        VIR_DEBUG("decided on firmware '%s' template '%s'",
+                  loader->path, NULLSTR(loader->nvramTemplate));
         break;
 
     case QEMU_FIRMWARE_DEVICE_KERNEL:
@@ -1360,58 +1358,99 @@ qemuFirmwareFetchParsedConfigs(bool privileged,
 }
 
 
-int
-qemuFirmwareFillDomain(virQEMUDriver *driver,
-                       virDomainDef *def,
-                       unsigned int flags)
+/**
+ * qemuFirmwareFillDomainLegacy:
+ * @driver: QEMU driver
+ * @def: domain definition
+ *
+ * Go through the legacy list of CODE:VARS pairs looking for a
+ * suitable NVRAM template for the user-provided firmware path.
+ *
+ * Should only be used as a fallback in case looking at the firmware
+ * descriptors yielded no results.
+ *
+ * Returns: 0 on success,
+ *          1 if a matching firmware could not be found,
+ *          -1 on error.
+ */
+static int
+qemuFirmwareFillDomainLegacy(virQEMUDriver *driver,
+                             virDomainDef *def)
 {
-    g_auto(GStrv) paths = NULL;
-    qemuFirmware **firmwares = NULL;
-    ssize_t nfirmwares = 0;
-    const qemuFirmware *theone = NULL;
-    bool needResult = true;
-    const bool reset_nvram = flags & VIR_QEMU_PROCESS_START_RESET_NVRAM;
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    virDomainLoaderDef *loader = def->os.loader;
     size_t i;
-    int ret = -1;
 
-    /* Fill in FW paths if either os.firmware is enabled, or
-     * loader path was provided with no nvram varstore. */
-    if (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE) {
-        /* This is horrific check, but loosely said, if UEFI
-         * image was provided by the old method (by specifying
-         * its path in domain XML) but no template for NVRAM was
-         * specified and the varstore doesn't exist ... */
-        if (!virDomainDefHasOldStyleROUEFI(def) ||
-            def->os.loader->nvramTemplate)
-            return 0;
+    if (!loader)
+        return 0;
 
-        if (def->os.loader->nvram) {
-            if (!virStorageSourceIsLocalStorage(def->os.loader->nvram)) {
-                if (reset_nvram) {
-                    virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
-                                   _("resetting of nvram is not supported with network backed nvram"));
-                    return -1;
-                }
-
-                /* we don't scrutinize whether NVRAM image accessed via network
-                 * is present */
-                return 0;
-            }
+    if (loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH) {
+        VIR_DEBUG("Ignoring legacy entries for '%s' loader",
+                  virDomainLoaderTypeToString(loader->type));
+        return 0;
+    }
 
-            if (!reset_nvram && virFileExists(def->os.loader->nvram->path))
-                return 0;
+    if (loader->stateless == VIR_TRISTATE_BOOL_YES) {
+        VIR_DEBUG("Ignoring legacy entries for stateless loader");
+        return 0;
+    }
+
+    for (i = 0; i < cfg->nfirmwares; i++) {
+        virFirmware *fw = cfg->firmwares[i];
+
+        if (STRNEQ(fw->name, loader->path)) {
+            VIR_DEBUG("Not matching loader path '%s' for user provided path '%s'",
+                      fw->name, loader->path);
+            continue;
         }
 
-        /* ... then we want to consult JSON FW descriptors first,
-         * but we don't want to fail if we haven't found a match. */
-        needResult = false;
-    } else {
-        /* Domain has FW autoselection enabled => do nothing if
-         * we are not starting it from scratch. */
-        if (!(flags & VIR_QEMU_PROCESS_START_NEW))
-            return 0;
+        loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
+        loader->readonly = VIR_TRISTATE_BOOL_YES;
+        loader->nvramTemplate = g_strdup(cfg->firmwares[i]->nvram);
+
+        if (!loader->nvram) {
+            loader->nvram = virStorageSourceNew();
+            loader->nvram->type = VIR_STORAGE_TYPE_FILE;
+            loader->nvram->format = VIR_STORAGE_FILE_RAW;
+            qemuDomainNVRAMPathFormat(cfg, def, &loader->nvram->path);
+        }
+
+        VIR_DEBUG("decided on firmware '%s' template '%s'",
+                  loader->path, NULLSTR(loader->nvramTemplate));
+
+        return 0;
     }
 
+    return 1;
+}
+
+
+/**
+ * qemuFirmwareFillDomainModern:
+ * @driver: QEMU driver
+ * @def: domain definition
+ *
+ * Look at the firmware descriptors available on the system and try
+ * to find one that matches the user's requested configuration. If
+ * successful, @def will be updated so that it explicitly points to
+ * the corresponding paths.
+ *
+ * Returns: 0 on success,
+ *          1 if a matching firmware could not be found,
+ *          -1 on error.
+ */
+static int
+qemuFirmwareFillDomainModern(virQEMUDriver *driver,
+                             virDomainDef *def)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    g_auto(GStrv) paths = NULL;
+    qemuFirmware **firmwares = NULL;
+    ssize_t nfirmwares = 0;
+    const qemuFirmware *theone = NULL;
+    size_t i;
+    int ret = -1;
+
     if ((nfirmwares = qemuFirmwareFetchParsedConfigs(driver->privileged,
                                                      &firmwares, &paths)) < 0)
         return -1;
@@ -1426,16 +1465,7 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
     }
 
     if (!theone) {
-        if (needResult) {
-            virReportError(VIR_ERR_OPERATION_FAILED,
-                           _("Unable to find any firmware to satisfy '%s'"),
-                           virDomainOsDefFirmwareTypeToString(def->os.firmware));
-        } else {
-            VIR_DEBUG("Unable to find NVRAM template for '%s', "
-                      "falling back to old style",
-                      NULLSTR(def->os.loader ? def->os.loader->path : NULL));
-            ret = 0;
-        }
+        ret = 1;
         goto cleanup;
     }
 
@@ -1444,13 +1474,14 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
      * likely that admin/FW manufacturer messed up. */
     qemuFirmwareSanityCheck(theone, paths[i]);
 
-    if (qemuFirmwareEnableFeatures(driver, def, theone) < 0)
+    if (qemuFirmwareEnableFeaturesModern(cfg, def, theone) < 0)
         goto cleanup;
 
     def->os.firmware = VIR_DOMAIN_OS_DEF_FIRMWARE_NONE;
     VIR_FREE(def->os.firmwareFeatures);
 
     ret = 0;
+
  cleanup:
     for (i = 0; i < nfirmwares; i++)
         qemuFirmwareFree(firmwares[i]);
@@ -1459,6 +1490,119 @@ qemuFirmwareFillDomain(virQEMUDriver *driver,
 }
 
 
+/**
+ * qemuFirmwareFillDomain:
+ * @driver: QEMU driver
+ * @def: domain definition
+ *
+ * Perform firmware selection.
+ *
+ * When firmware autoselection is used, this means looking at the
+ * firmware descriptors available on the system and finding one that
+ * matches the user's requested parameters; when manual firmware
+ * selection is used, the path to the firmware itself is usually
+ * already provided, but other information such as the path to the
+ * NVRAM template might be missing.
+ *
+ * The idea is that calling this function a first time (at PostParse
+ * time) will convert whatever partial configuration the user might
+ * have provided into a fully specified firmware configuration, such
+ * as that calling it a second time (at domain start time) will
+ * result in an early successful exit. The same thing should happen
+ * if the input configuration wasn't missing any information in the
+ * first place.
+ *
+ * Returns: 0 on success,
+ *          -1 on error.
+ */
+int
+qemuFirmwareFillDomain(virQEMUDriver *driver,
+                       virDomainDef *def)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    virDomainLoaderDef *loader = def->os.loader;
+    bool autoSelection = (def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE);
+    int ret;
+
+    /* Start by performing a thorough validation of the input.
+     *
+     * We need to do this here because the firmware selection logic
+     * can only work correctly if the request is constructed
+     * properly; at the same time, we can't rely on Validate having
+     * been called ahead of time, because in some situations (such as
+     * when loading the configuration of existing domains from disk)
+     * that entire phase is intentionally skipped */
+    if (virDomainDefOSValidate(def, NULL) < 0)
+        return -1;
+
+    /* If firmware autoselection is disabled and the loader is a ROM
+     * instead of a PFLASH device, then we're using BIOS and we don't
+     * need any information at all */
+    if (!autoSelection &&
+        (!loader || (loader && loader->type == VIR_DOMAIN_LOADER_TYPE_ROM))) {
+        return 0;
+    }
+
+    /* For UEFI with firmware autoselection disabled, even if some of
+     * the information is missing we might still be able to avoid
+     * having to look at firmware descriptors */
+    if (!autoSelection &&
+        virDomainDefHasOldStyleROUEFI(def) &&
+        loader->path) {
+
+        /* For stateless firmwares, the firmware path is all we need */
+        if (loader->stateless == VIR_TRISTATE_BOOL_YES)
+            return 0;
+
+        /* If the path to the NVRAM file is already provided and it
+         * points to a non-local source, we don't need to look up any
+         * other information */
+        if (loader->nvram && !virStorageSourceIsLocalStorage(loader->nvram))
+            return 0;
+
+        /* If we have the path to both the firmware itself and the
+         * corresponding NVRAM template we might still need to
+         * generate a path to the domain-specific NVRAM file, but
+         * otherwise we're good to go */
+        if (loader->nvramTemplate) {
+            if (!loader->nvram) {
+                loader->nvram = virStorageSourceNew();
+                loader->nvram->type = VIR_STORAGE_TYPE_FILE;
+                loader->nvram->format = VIR_STORAGE_FILE_RAW;
+                qemuDomainNVRAMPathFormat(cfg, def, &loader->nvram->path);
+            }
+            return 0;
+        }
+    }
+
+    /* Look for the information we need in firmware descriptors */
+    if ((ret = qemuFirmwareFillDomainModern(driver, def)) < 0)
+        return -1;
+
+    if (ret == 1) {
+        /* If we haven't found any match among firmware descriptors,
+         * that would normally be the end of it.
+         *
+         * However, in order to handle legacy configurations
+         * correctly, we make another attempt at locating the missing
+         * information by going through the hardcoded list of
+         * CODE:NVRAM pairs that might have been provided at build
+         * time */
+        if (!autoSelection) {
+            if (qemuFirmwareFillDomainLegacy(driver, def) < 0)
+                return -1;
+        } else {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("Unable to find any firmware to satisfy '%s'"),
+                           virDomainOsDefFirmwareTypeToString(def->os.firmware));
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
 /**
  * qemuFirmwareGetSupported:
  * @machine: machine type
index 103b6e4643854faace0caa0a89b071b0a7a39e79..1ce09207130775c08cf3132c84ad880c0f0a0b9a 100644 (file)
@@ -44,8 +44,7 @@ qemuFirmwareFetchConfigs(char ***firmwares,
 
 int
 qemuFirmwareFillDomain(virQEMUDriver *driver,
-                       virDomainDef *def,
-                       unsigned int flags);
+                       virDomainDef *def);
 
 int
 qemuFirmwareGetSupported(const char *machine,
index 63d7e1138d08ed1581bc569f43b438024ad97618..1218edc99b90612deb1764baea0f966ba6f8e621 100644 (file)
@@ -4601,42 +4601,41 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
     VIR_AUTOCLOSE srcFD = -1;
     virDomainLoaderDef *loader = vm->def->os.loader;
-    const char *master_nvram_path;
     struct qemuPrepareNVRAMHelperData data;
 
-    if (!loader || !loader->nvram ||
-        !virStorageSourceIsLocalStorage(loader->nvram) ||
-        (virFileExists(loader->nvram->path) && !reset_nvram))
+    if (!loader || !loader->nvram)
         return 0;
 
-    master_nvram_path = loader->nvramTemplate;
-    if (!loader->nvramTemplate) {
-        size_t i;
-        for (i = 0; i < cfg->nfirmwares; i++) {
-            if (STREQ(cfg->firmwares[i]->name, loader->path)) {
-                master_nvram_path = cfg->firmwares[i]->nvram;
-                break;
-            }
+    if (!virStorageSourceIsLocalStorage(loader->nvram)) {
+        if (!reset_nvram) {
+            return 0;
+        } else {
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                    _("resetting of nvram is not supported with network backed nvram"));
+            return -1;
         }
     }
 
-    if (!master_nvram_path) {
+    if (virFileExists(loader->nvram->path) && !reset_nvram)
+        return 0;
+
+    if (!loader->nvramTemplate) {
         virReportError(VIR_ERR_OPERATION_FAILED,
                        _("unable to find any master var store for "
                          "loader: %s"), loader->path);
         return -1;
     }
 
-    if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY,
+    if ((srcFD = virFileOpenAs(loader->nvramTemplate, O_RDONLY,
                                0, -1, -1, 0)) < 0) {
         virReportSystemError(-srcFD,
                              _("Failed to open file '%s'"),
-                             master_nvram_path);
+                             loader->nvramTemplate);
         return -1;
     }
 
     data.srcFD = srcFD;
-    data.srcPath = master_nvram_path;
+    data.srcPath = loader->nvramTemplate;
 
     if (virFileRewrite(loader->nvram->path,
                        S_IRUSR | S_IWUSR,
@@ -6769,7 +6768,7 @@ qemuProcessPrepareDomain(virQEMUDriver *driver,
         return -1;
 
     VIR_DEBUG("Prepare bios/uefi paths");
-    if (qemuFirmwareFillDomain(driver, vm->def, flags) < 0)
+    if (qemuFirmwareFillDomain(driver, vm->def) < 0)
         return -1;
     if (qemuDomainInitializePflashStorageSource(vm, cfg) < 0)
         return -1;
index b4e7e0a94446f66287493cd54b9628b2e3752a87..24109a11c31966372f6cececbeb95a0de0f33c39 100644 (file)
@@ -12,7 +12,7 @@
   <os>
     <type arch='aarch64' machine='virt'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
-    <nvram>/some/user/nvram/path/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/some/user/nvram/path/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 3a7961df1055ec09bb1ef61f3ae9d2fccd544313..6182da4dc6393702f2a49995cea4c1d8d9be7241 100644 (file)
@@ -12,7 +12,7 @@
   <os>
     <type arch='aarch64' machine='virt'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
-    <nvram>/some/user/nvram/path/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/some/user/nvram/path/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 9d42e210c3ee66514d9a2fa1f8c0784331319b1d..c7c6e23ea1294eb1c744a2789db944532aa21466 100644 (file)
@@ -4,9 +4,9 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='bios'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <loader stateless='yes'/>
+    <loader type='rom' stateless='yes'>/usr/share/seabios/bios-256k.bin</loader>
     <boot dev='hd'/>
   </os>
   <features>
index 11f95f04eb7d4eb62013f85c707dc1f0961ffb0c..4e0b45cccde619d88c83e7007f3e1c5eab52a64e 100644 (file)
@@ -4,8 +4,9 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='bios'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
+    <loader type='rom'>/usr/share/seabios/bios-256k.bin</loader>
     <boot dev='hd'/>
   </os>
   <features>
index 5f4432db36730133282252297eee3e8826ea0cf7..b53f39a72e5821143d7bbd7d7090826197c02a40 100644 (file)
@@ -4,8 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='aarch64' machine='virt-4.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 3923d1d4f2b39742397949e0489d34d264d0adbc..68147847217dcdf1c72478c680169495bf73c14b 100644 (file)
@@ -4,16 +4,15 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <firmware>
-      <feature enabled='yes' name='enrolled-keys'/>
-      <feature enabled='yes' name='secure-boot'/>
-    </firmware>
+    <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
     <acpi/>
+    <smm state='on'/>
   </features>
   <cpu mode='custom' match='exact' check='none'>
     <model fallback='forbid'>qemu64</model>
index c655d81454025c2305c554ad860aca643a4438d2..68147847217dcdf1c72478c680169495bf73c14b 100644 (file)
@@ -4,13 +4,15 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <loader secure='yes'/>
+    <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
     <acpi/>
+    <smm state='on'/>
   </features>
   <cpu mode='custom' match='exact' check='none'>
     <model fallback='forbid'>qemu64</model>
index 326b1d5fafafcd7f598926d1cb0c9e3b3f4e02d8..8b3853dc171da870a59048679804c6c250e13783 100644 (file)
@@ -4,11 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <firmware>
-      <feature enabled='no' name='enrolled-keys'/>
-    </firmware>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 9e8107cb4d163cf4b58abdbd40b29be4d4919137..8b3853dc171da870a59048679804c6c250e13783 100644 (file)
@@ -4,11 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <firmware>
-      <feature enabled='no' name='secure-boot'/>
-    </firmware>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 961e97472d0cf458425bc0b5e784073f0c669f2e..cdb5d2b31a91033f4a40ed017784b14e52aa1acc 100644 (file)
@@ -4,9 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-i440fx-4.0'>hvm</type>
-    <nvram type='file'>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd' type='file'>
       <source file='/path/to/guest_VARS.fd'/>
     </nvram>
     <boot dev='hd'/>
index 446266fbf0bc9053189104115ec63cecbf69c8bc..5a2e8715a01db920696cd265537c1553e36b26a1 100644 (file)
@@ -4,8 +4,9 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-i440fx-4.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
     <nvram type='network'>
       <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool'>
         <host name='example.com' port='6000'/>
index 4f0d9bef1ed0de53ff613bf022d0cb9812f7e671..208257bb5b33de1478d9a784cf2eef1d7fdcfff2 100644 (file)
@@ -4,8 +4,9 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-i440fx-4.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
     <nvram type='network'>
       <source protocol='nbd' name='bar'>
         <host name='example.org' port='6000'/>
index 2090a770c6b468401c1c3a1f6eeb29943d770955..f039d79ae495c00a957daaf4df882f99b5e67647 100644 (file)
@@ -4,13 +4,15 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
     <acpi/>
+    <smm state='on'/>
   </features>
   <cpu mode='custom' match='exact' check='none'>
     <model fallback='forbid'>qemu64</model>
index 22a26554c875859237a03b8f8a901fc87b83cad5..68147847217dcdf1c72478c680169495bf73c14b 100644 (file)
@@ -4,15 +4,15 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <firmware>
-      <feature enabled='yes' name='secure-boot'/>
-    </firmware>
+    <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
     <acpi/>
+    <smm state='on'/>
   </features>
   <cpu mode='custom' match='exact' check='none'>
     <model fallback='forbid'>qemu64</model>
index 7274753f9d9050d8e5d77d4cce59fb87cbeff684..3a50158fba996e78e6b86519902a4e403fa1acda 100644 (file)
@@ -4,8 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 143756dbff8dfb314c93f0bef8c7c9741569c291..3bc9a7341eb29444e9992e36bca44f448d7128b7 100644 (file)
@@ -4,9 +4,9 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
-    <loader stateless='yes'/>
+    <loader readonly='yes' type='pflash' stateless='yes'>/usr/share/OVMF/OVMF.sev.fd</loader>
     <boot dev='hd'/>
   </os>
   <features>
index 72f2ea1321640f4ef1a686731d6aebdf8c4cc46e..68147847217dcdf1c72478c680169495bf73c14b 100644 (file)
@@ -4,12 +4,15 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
+    <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
     <acpi/>
+    <smm state='on'/>
   </features>
   <cpu mode='custom' match='exact' check='none'>
     <model fallback='forbid'>qemu64</model>
index 24e4de6fc6ee3347ab8be620c15b4930ac7878e0..34257e4f80fd6679f194adaff9c401f8858f379d 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='aarch64' machine='virt-4.0'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 2a36c46737c284184565fe0ffd23b1497d6a4ea2..ff7793a377ccd74e9f58f7894ddf08e5d5dc964f 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 414c1d6611651bc29d110744b2ca64b0c5dfde56..1f642cd1793cfee2c675a29aff9f497e83b8dba5 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='aarch64' machine='virt-4.0'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 482d7987f6b1aa926bdb9414bb930277b4c9079e..cdb5d2b31a91033f4a40ed017784b14e52aa1acc 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='x86_64' machine='pc-i440fx-4.0'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
-    <nvram type='file'>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd' type='file'>
       <source file='/path/to/guest_VARS.fd'/>
     </nvram>
     <boot dev='hd'/>
index cd7de760344796247337889dc7fb35810b47ab66..aa90d3e2f2364d1fa2240cfe8dec71793562ceff 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='x86_64' machine='pc-q35-4.0'>hvm</type>
     <loader readonly='yes' secure='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.secboot.fd</loader>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.secboot.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 97a9a6c5e65d06e3be49dfeb02d08648eff543f5..ff6460d7b03223326835a97c54e9b13b12eb2dd2 100644 (file)
@@ -7,7 +7,7 @@
   <os>
     <type arch='x86_64' machine='pc-i440fx-4.0'>hvm</type>
     <loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader>
-    <nvram>/path/to/guest_VARS.fd</nvram>
+    <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/path/to/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index eb0809af7c21edb20701152dab1a54fea5ab4661..18ad2db8118b17c629fcb897c716bf54784bda8d 100644 (file)
@@ -4,8 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='aarch64' machine='virt-6.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 2812242023a5554d516d10564d62bb5699146c4b..3018fc29fa52e36e2463161d717bedcc0aaadc33 100644 (file)
@@ -4,8 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='aarch64' machine='virt-6.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>
index 19b881ce313657fea0e0054566ebb7b727bd6b89..2813e742d16fe7f83c6589e35790d57e0424b753 100644 (file)
@@ -4,8 +4,10 @@
   <memory unit='KiB'>1048576</memory>
   <currentMemory unit='KiB'>1048576</currentMemory>
   <vcpu placement='static'>1</vcpu>
-  <os firmware='efi'>
+  <os>
     <type arch='aarch64' machine='virt-6.0'>hvm</type>
+    <loader readonly='yes' type='pflash'>/usr/share/AAVMF/AAVMF_CODE.fd</loader>
+    <nvram template='/usr/share/AAVMF/AAVMF_VARS.fd'>/var/lib/libvirt/qemu/nvram/guest_VARS.fd</nvram>
     <boot dev='hd'/>
   </os>
   <features>