[libvirt] [PATCH v1 3/4] qemu_firmware: Introduce qemuFirmwareGetSupported

Michal Privoznik mprivozn at redhat.com
Fri Apr 5 07:19:47 UTC 2019


The point of this API is to fetch all FW descriptors, parse them
and return list of supported interfaces for given combination of
machine type and guest architecture.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_firmware.c | 51 ++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_firmware.h |  9 +++++++
 tests/qemufirmwaretest.c | 58 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index 8e9a225982..07ac47c62b 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -1349,7 +1349,8 @@ qemuFirmwareFetchParsedConfigs(bool privileged,
     }
 
     VIR_STEAL_PTR(*firmwaresRet, firmwares);
-    VIR_STEAL_PTR(*pathsRet, paths);
+    if (pathsRet)
+        VIR_STEAL_PTR(*pathsRet, paths);
     return npaths;
 
  error:
@@ -1415,3 +1416,51 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver,
     VIR_FREE(firmwares);
     return ret;
 }
+
+
+int
+qemuFirmwareGetSupported(const char *machine,
+                         virArch arch,
+                         bool privileged,
+                         unsigned int *supported)
+{
+    qemuFirmwarePtr *firmwares = NULL;
+    ssize_t nfirmwares = 0;
+    size_t i;
+
+    *supported = VIR_DOMAIN_OS_DEF_FIRMWARE_NONE;
+
+    if ((nfirmwares = qemuFirmwareFetchParsedConfigs(privileged,
+                                                     &firmwares, NULL)) < 0)
+        return -1;
+
+    for (i = 0; i < nfirmwares; i++) {
+        qemuFirmwarePtr fw = firmwares[i];
+        size_t j;
+
+        if (!qemuFirmwareMatchesMachineArch(fw, machine, arch))
+            continue;
+
+        for (j = 0; j < fw->ninterfaces; j++) {
+            switch (fw->interfaces[j]) {
+            case QEMU_FIRMWARE_OS_INTERFACE_UEFI:
+                *supported |= (1 << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
+                break;
+            case QEMU_FIRMWARE_OS_INTERFACE_BIOS:
+                *supported |= (1 << VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
+                break;
+            case QEMU_FIRMWARE_OS_INTERFACE_NONE:
+            case QEMU_FIRMWARE_OS_INTERFACE_OPENFIRMWARE:
+            case QEMU_FIRMWARE_OS_INTERFACE_UBOOT:
+            case QEMU_FIRMWARE_OS_INTERFACE_LAST:
+            default:
+                break;
+            }
+        }
+    }
+
+    for (i = 0; i < nfirmwares; i++)
+        qemuFirmwareFree(firmwares[i]);
+    VIR_FREE(firmwares);
+    return 0;
+}
diff --git a/src/qemu/qemu_firmware.h b/src/qemu/qemu_firmware.h
index 7f8a0e4a15..0be5284ac1 100644
--- a/src/qemu/qemu_firmware.h
+++ b/src/qemu/qemu_firmware.h
@@ -24,6 +24,7 @@
 # include "domain_conf.h"
 # include "viralloc.h"
 # include "qemu_conf.h"
+# include "virarch.h"
 
 typedef struct _qemuFirmware qemuFirmware;
 typedef qemuFirmware *qemuFirmwarePtr;
@@ -48,4 +49,12 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver,
                        virDomainObjPtr vm,
                        unsigned int flags);
 
+int
+qemuFirmwareGetSupported(const char *machine,
+                         virArch arch,
+                         bool privileged,
+                         unsigned int *supported);
+
+verify(sizeof(unsigned int) >= ((1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_LAST) >> 2));
+
 #endif /* LIBVIRT_QEMU_FIRMWARE_H */
diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c
index 2b5cbf649b..9e9dfd9b1b 100644
--- a/tests/qemufirmwaretest.c
+++ b/tests/qemufirmwaretest.c
@@ -99,6 +99,42 @@ testFWPrecedence(const void *opaque ATTRIBUTE_UNUSED)
 }
 
 
+struct supportedData {
+    const char *machine;
+    virArch arch;
+    unsigned int *interfaces;
+    size_t ninterfaces;
+};
+
+
+static int
+testSupportedFW(const void *opaque)
+{
+    const struct supportedData *data = opaque;
+    unsigned int actual;
+    unsigned int expected = 0;
+    size_t i;
+
+    for (i = 0; i < data->ninterfaces; i++)
+        expected |= (1 << data->interfaces[i]);
+
+    if (qemuFirmwareGetSupported(data->machine, data->arch, false, &actual) < 0) {
+        fprintf(stderr, "Unable to get list of supported interfaces\n");
+        return -1;
+    }
+
+    if (actual != expected) {
+        fprintf(stderr,
+                "Mismatch in supported interfaces. "
+                "Expected 0x%x got 0x%x\n",
+                expected, actual);
+        return -1;
+    }
+
+    return 0;
+}
+
+
 static int
 mymain(void)
 {
@@ -127,6 +163,28 @@ mymain(void)
     if (virTestRun("QEMU FW precedence test", testFWPrecedence, NULL) < 0)
         ret = -1;
 
+#define DO_SUPPORTED_TEST(machine, arch, ...) \
+    do { \
+        unsigned int interfaces[] = {__VA_ARGS__}; \
+        struct supportedData data = {machine, arch, interfaces, ARRAY_CARDINALITY(interfaces)}; \
+        if (virTestRun("QEMU FW SUPPORTED " machine " " #arch, \
+                       testSupportedFW, &data) < 0) \
+            ret = -1; \
+    } while (0)
+
+    DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
+    DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
+    DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
+    DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
+    DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64,
+                      VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
+
     virFileWrapperClearPrefixes();
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-- 
2.21.0




More information about the libvir-list mailing list