[libvirt] [PATCH V2 1/6] driver config: Introduce virFirmware object

Jim Fehlig jfehlig at suse.com
Wed Jun 8 23:23:02 UTC 2016


The virQEMUDriverConfig object contains lists of
loader:nvram pairs to advertise firmwares supported by
by the driver, and qemu_conf.c contains code to populate
the lists, all of which is useful for other drivers too.

To avoid code duplication, introduce a virFirmware object
to encapsulate firmware details and switch the qemu driver
to use it.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
---
 po/POTFILES.in               |   1 +
 src/Makefile.am              |   1 +
 src/libvirt_private.syms     |   6 ++
 src/qemu/qemu_capabilities.c |  22 +++----
 src/qemu/qemu_capabilities.h |   5 +-
 src/qemu/qemu_conf.c         | 127 ++++++---------------------------------
 src/qemu/qemu_conf.h         |   7 +--
 src/qemu/qemu_driver.c       |   2 +-
 src/qemu/qemu_process.c      |   6 +-
 src/util/virfirmware.c       | 137 +++++++++++++++++++++++++++++++++++++++++++
 src/util/virfirmware.h       |  51 ++++++++++++++++
 tests/domaincapstest.c       |   3 +-
 12 files changed, 237 insertions(+), 131 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2a6fae4..85adaf3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -194,6 +194,7 @@ src/util/virerror.h
 src/util/vireventpoll.c
 src/util/virfile.c
 src/util/virfirewall.c
+src/util/virfirmware.c
 src/util/virhash.c
 src/util/virhook.c
 src/util/virhostdev.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 8c83b0c..9c4eb41 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -114,6 +114,7 @@ UTIL_SOURCES =							\
 		util/virfile.c util/virfile.h			\
 		util/virfirewall.c util/virfirewall.h		\
 		util/virfirewallpriv.h				\
+		util/virfirmware.c util/virfirmware.h		\
 		util/virgettext.c util/virgettext.h		\
 		util/virgic.c util/virgic.h			\
 		util/virhash.c util/virhash.h			\
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 27ad7ff..bed4e11 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1561,6 +1561,12 @@ virFirewallStartRollback;
 virFirewallStartTransaction;
 
 
+# util/virfirmware.h
+virFirmwareFreeList;
+virFirmwareParse;
+virFirmwareParseList;
+
+
 # util/virgettext.h
 virGettextInitialize;
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 43ac906..cdb3b6c 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -4069,18 +4069,18 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps)
 
 static int
 virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoaderPtr capsLoader,
-                                char **loader,
-                                size_t nloader)
+                                virFirmwarePtr *firmwares,
+                                size_t nfirmwares)
 {
     size_t i;
 
     capsLoader->supported = true;
 
-    if (VIR_ALLOC_N(capsLoader->values.values, nloader) < 0)
+    if (VIR_ALLOC_N(capsLoader->values.values, nfirmwares) < 0)
         return -1;
 
-    for (i = 0; i < nloader; i++) {
-        const char *filename = loader[i];
+    for (i = 0; i < nfirmwares; i++) {
+        const char *filename = firmwares[i]->name;
 
         if (!virFileExists(filename)) {
             VIR_DEBUG("loader filename=%s does not exist", filename);
@@ -4109,13 +4109,13 @@ virQEMUCapsFillDomainLoaderCaps(virDomainCapsLoaderPtr capsLoader,
 
 static int
 virQEMUCapsFillDomainOSCaps(virDomainCapsOSPtr os,
-                            char **loader,
-                            size_t nloader)
+                            virFirmwarePtr *firmwares,
+                            size_t nfirmwares)
 {
     virDomainCapsLoaderPtr capsLoader = &os->loader;
 
     os->supported = true;
-    if (virQEMUCapsFillDomainLoaderCaps(capsLoader, loader, nloader) < 0)
+    if (virQEMUCapsFillDomainLoaderCaps(capsLoader, firmwares, nfirmwares) < 0)
         return -1;
     return 0;
 }
@@ -4328,8 +4328,8 @@ virQEMUCapsFillDomainFeatureGICCaps(virQEMUCapsPtr qemuCaps,
 int
 virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
                           virQEMUCapsPtr qemuCaps,
-                          char **loader,
-                          size_t nloader)
+                          virFirmwarePtr *firmwares,
+                          size_t nfirmwares)
 {
     virDomainCapsOSPtr os = &domCaps->os;
     virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
@@ -4340,7 +4340,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
 
     domCaps->maxvcpus = maxvcpus;
 
-    if (virQEMUCapsFillDomainOSCaps(os, loader, nloader) < 0 ||
+    if (virQEMUCapsFillDomainOSCaps(os, firmwares, nfirmwares) < 0 ||
         virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps,
                                             domCaps->machine, disk) < 0 ||
         virQEMUCapsFillDomainDeviceGraphicsCaps(qemuCaps, graphics) < 0 ||
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 77e4b98..39c642c 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -29,6 +29,7 @@
 # include "vircommand.h"
 # include "qemu_monitor.h"
 # include "domain_capabilities.h"
+# include "virfirmware.h"
 
 /*
  * Internal flags to keep track of qemu command line capabilities
@@ -490,7 +491,7 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
 
 int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
                               virQEMUCapsPtr qemuCaps,
-                              char **loader,
-                              size_t nloader);
+                              virFirmwarePtr *firmwares,
+                              size_t nfirmwares);
 
 #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index e00ddca..030bd5a 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -124,47 +124,6 @@ void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def)
 }
 
 
-static int ATTRIBUTE_UNUSED
-virQEMUDriverConfigLoaderNVRAMParse(virQEMUDriverConfigPtr cfg,
-                                    const char *list)
-{
-    int ret = -1;
-    char **token;
-    size_t i, j;
-
-    if (!(token = virStringSplit(list, ":", 0)))
-        goto cleanup;
-
-    for (i = 0; token[i]; i += 2) {
-        if (!token[i] || !token[i + 1] ||
-            STREQ(token[i], "") || STREQ(token[i + 1], "")) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Invalid --with-loader-nvram list: %s"),
-                           list);
-            goto cleanup;
-        }
-    }
-
-    if (i) {
-        if (VIR_ALLOC_N(cfg->loader, i / 2) < 0 ||
-            VIR_ALLOC_N(cfg->nvram, i / 2) < 0)
-            goto cleanup;
-        cfg->nloader = i / 2;
-
-        for (j = 0; j < i / 2; j++) {
-            if (VIR_STRDUP(cfg->loader[j], token[2 * j]) < 0 ||
-                VIR_STRDUP(cfg->nvram[j], token[2 * j + 1]) < 0)
-                goto cleanup;
-        }
-    }
-
-    ret = 0;
- cleanup:
-    virStringFreeList(token);
-    return ret;
-}
-
-
 #define VIR_QEMU_OVMF_LOADER_PATH "/usr/share/OVMF/OVMF_CODE.fd"
 #define VIR_QEMU_OVMF_NVRAM_PATH "/usr/share/OVMF/OVMF_VARS.fd"
 #define VIR_QEMU_AAVMF_LOADER_PATH "/usr/share/AAVMF/AAVMF_CODE.fd"
@@ -327,20 +286,22 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
     cfg->stdioLogD = true;
 
 #ifdef DEFAULT_LOADER_NVRAM
-    if (virQEMUDriverConfigLoaderNVRAMParse(cfg, DEFAULT_LOADER_NVRAM) < 0)
+    if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
+                             &cfg->firmwares,
+                             &cfg->nfirmwares) < 0)
         goto error;
 
 #else
-
-    if (VIR_ALLOC_N(cfg->loader, 2) < 0 ||
-        VIR_ALLOC_N(cfg->nvram, 2) < 0)
+    if (VIR_ALLOC_N(cfg->firmwares, 2) < 0)
+        goto error;
+    cfg->nfirmwares = 2;
+    if (VIR_ALLOC(cfg->firmwares[0]) < 0 || VIR_ALLOC(cfg->firmwares[1]) < 0)
         goto error;
-    cfg->nloader = 2;
 
-    if (VIR_STRDUP(cfg->loader[0], VIR_QEMU_AAVMF_LOADER_PATH) < 0 ||
-        VIR_STRDUP(cfg->nvram[0], VIR_QEMU_AAVMF_NVRAM_PATH) < 0  ||
-        VIR_STRDUP(cfg->loader[1], VIR_QEMU_OVMF_LOADER_PATH) < 0 ||
-        VIR_STRDUP(cfg->nvram[1], VIR_QEMU_OVMF_NVRAM_PATH) < 0)
+    if (VIR_STRDUP(cfg->firmwares[0]->name, VIR_QEMU_AAVMF_LOADER_PATH) < 0 ||
+        VIR_STRDUP(cfg->firmwares[0]->nvram, VIR_QEMU_AAVMF_NVRAM_PATH) < 0  ||
+        VIR_STRDUP(cfg->firmwares[1]->name, VIR_QEMU_OVMF_LOADER_PATH) < 0 ||
+        VIR_STRDUP(cfg->firmwares[1]->nvram, VIR_QEMU_OVMF_NVRAM_PATH) < 0)
         goto error;
 #endif
 
@@ -397,13 +358,7 @@ static void virQEMUDriverConfigDispose(void *obj)
 
     VIR_FREE(cfg->lockManagerName);
 
-    while (cfg->nloader) {
-        VIR_FREE(cfg->loader[cfg->nloader - 1]);
-        VIR_FREE(cfg->nvram[cfg->nloader - 1]);
-        cfg->nloader--;
-    }
-    VIR_FREE(cfg->loader);
-    VIR_FREE(cfg->nvram);
+    virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
 }
 
 
@@ -427,43 +382,6 @@ virQEMUDriverConfigHugeTLBFSInit(virHugeTLBFSPtr hugetlbfs,
 }
 
 
-static int
-virQEMUDriverConfigNVRAMParse(const char *str,
-                              char **loader,
-                              char **nvram)
-{
-    int ret = -1;
-    char **token;
-
-    if (!(token = virStringSplit(str, ":", 0)))
-        goto cleanup;
-
-    if (token[0]) {
-        virSkipSpaces((const char **) &token[0]);
-        if (token[1])
-            virSkipSpaces((const char **) &token[1]);
-    }
-
-    /* Exactly two tokens are expected */
-    if (!token[0] || !token[1] || token[2] ||
-        STREQ(token[0], "") || STREQ(token[1], "")) {
-        virReportError(VIR_ERR_CONF_SYNTAX,
-                       _("Invalid nvram format: '%s'"),
-                       str);
-        goto cleanup;
-    }
-
-    if (VIR_STRDUP(*loader, token[0]) < 0 ||
-        VIR_STRDUP(*nvram, token[1]) < 0)
-        goto cleanup;
-
-    ret = 0;
- cleanup:
-    virStringFreeList(token);
-    return ret;
-}
-
-
 int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
                                 const char *filename)
 {
@@ -854,14 +772,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
 
         CHECK_TYPE("nvram", VIR_CONF_LIST);
 
-        while (cfg->nloader) {
-            VIR_FREE(cfg->loader[cfg->nloader - 1]);
-            VIR_FREE(cfg->nvram[cfg->nloader - 1]);
-            cfg->nloader--;
-        }
-        VIR_FREE(cfg->loader);
-        VIR_FREE(cfg->nvram);
-
+        virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
         /* Calc length and check items */
         for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
             if (pp->type != VIR_CONF_STRING) {
@@ -871,16 +782,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
             }
         }
 
-        if (len &&
-            (VIR_ALLOC_N(cfg->loader, len) < 0 ||
-             VIR_ALLOC_N(cfg->nvram, len) < 0))
+        if (len && VIR_ALLOC_N(cfg->firmwares, len) < 0)
             goto cleanup;
-        cfg->nloader = len;
+        cfg->nfirmwares = len;
 
         for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
-            if (virQEMUDriverConfigNVRAMParse(pp->str,
-                                              &cfg->loader[i],
-                                              &cfg->nvram[i]) < 0)
+            if (VIR_ALLOC(cfg->firmwares[i]) < 0)
+                goto cleanup;
+            if (virFirmwareParse(pp->str, cfg->firmwares[i]) < 0)
                 goto cleanup;
         }
     }
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 1fdef70..469b1dc 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -48,6 +48,7 @@
 # include "virclosecallbacks.h"
 # include "virhostdev.h"
 # include "virfile.h"
+# include "virfirmware.h"
 
 # ifdef CPU_SETSIZE /* Linux */
 #  define QEMUD_CPUMASK_LEN CPU_SETSIZE
@@ -177,10 +178,8 @@ struct _virQEMUDriverConfig {
     bool logTimestamp;
     bool stdioLogD;
 
-    /* Pairs of loader:nvram paths. The list is @nloader items long */
-    char **loader;
-    char **nvram;
-    size_t nloader;
+    virFirmwarePtr *firmwares;
+    size_t nfirmwares;
 };
 
 /* Main driver state */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e70d3ce..45f6a82 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18511,7 +18511,7 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
         goto cleanup;
 
     if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps,
-                                  cfg->loader, cfg->nloader) < 0)
+                                  cfg->firmwares, cfg->nfirmwares) < 0)
         goto cleanup;
 
     ret = virDomainCapsFormat(domCaps);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 397dac7..0b08df5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3727,9 +3727,9 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg,
     master_nvram_path = loader->templt;
     if (!loader->templt) {
         size_t i;
-        for (i = 0; i < cfg->nloader; i++) {
-            if (STREQ(cfg->loader[i], loader->path)) {
-                master_nvram_path = cfg->nvram[i];
+        for (i = 0; i < cfg->nfirmwares; i++) {
+            if (STREQ(cfg->firmwares[i]->name, loader->path)) {
+                master_nvram_path = cfg->firmwares[i]->nvram;
                 break;
             }
         }
diff --git a/src/util/virfirmware.c b/src/util/virfirmware.c
new file mode 100644
index 0000000..6b20c06
--- /dev/null
+++ b/src/util/virfirmware.c
@@ -0,0 +1,137 @@
+/*
+ * virfirmware.c: Definition of firmware object and supporting functions
+ *
+ * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Jim Fehlig <jfehlig at suse.com>
+ */
+
+#include <config.h>
+
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfirmware.h"
+#include "virlog.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.firmware");
+
+
+static void
+virFirmwareFree(virFirmwarePtr firmware)
+{
+    if (!firmware)
+        return;
+
+    VIR_FREE(firmware->name);
+    VIR_FREE(firmware->nvram);
+    VIR_FREE(firmware);
+}
+
+
+void
+virFirmwareFreeList(virFirmwarePtr *firmwares, size_t nfirmwares)
+{
+    size_t i;
+
+    for (i = 0; i < nfirmwares; i++)
+        virFirmwareFree(firmwares[i]);
+
+    VIR_FREE(firmwares);
+}
+
+
+int
+virFirmwareParse(const char *str, virFirmwarePtr firmware)
+{
+    int ret = -1;
+    char **token;
+
+    if (!(token = virStringSplit(str, ":", 0)))
+        goto cleanup;
+
+    if (token[0]) {
+        virSkipSpaces((const char **) &token[0]);
+        if (token[1])
+            virSkipSpaces((const char **) &token[1]);
+    }
+
+    /* Exactly two tokens are expected */
+    if (!token[0] || !token[1] || token[2] ||
+        STREQ(token[0], "") || STREQ(token[1], "")) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("Invalid nvram format: '%s'"),
+                       str);
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(firmware->name, token[0]) < 0 ||
+        VIR_STRDUP(firmware->nvram, token[1]) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virStringFreeList(token);
+    return ret;
+}
+
+
+int
+virFirmwareParseList(const char *list,
+                     virFirmwarePtr **firmwares,
+                     size_t *nfirmwares)
+{
+    int ret = -1;
+    char **token;
+    size_t i, j;
+
+    if (!(token = virStringSplit(list, ":", 0)))
+        goto cleanup;
+
+    for (i = 0; token[i]; i += 2) {
+        if (!token[i] || !token[i + 1] ||
+            STREQ(token[i], "") || STREQ(token[i + 1], "")) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Invalid --with-loader-nvram list: %s"),
+                           list);
+            goto cleanup;
+        }
+    }
+
+    if (i) {
+        if (VIR_ALLOC_N(*firmwares, i / 2) < 0)
+            goto cleanup;
+        *nfirmwares = i / 2;
+
+        for (j = 0; j < i / 2; j++) {
+            virFirmwarePtr *fws = *firmwares;
+
+            if (VIR_ALLOC(fws[j]) < 0)
+                goto cleanup;
+            if (VIR_STRDUP(fws[j]->name, token[2 * j]) < 0 ||
+                VIR_STRDUP(fws[j]->nvram, token[2 * j + 1]) < 0)
+                goto cleanup;
+        }
+    }
+
+    ret = 0;
+ cleanup:
+    virStringFreeList(token);
+    return ret;
+}
diff --git a/src/util/virfirmware.h b/src/util/virfirmware.h
new file mode 100644
index 0000000..682a865
--- /dev/null
+++ b/src/util/virfirmware.h
@@ -0,0 +1,51 @@
+/*
+ * virfirmware.h: Declaration of firmware object and supporting functions
+ *
+ * Copyright (C) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Jim Fehlig <jfehlig at suse.com>
+ */
+
+#ifndef __VIR_FIRMWARE_H__
+# define __VIR_FIRMWARE_H__
+
+# include "internal.h"
+
+typedef struct _virFirmware virFirmware;
+typedef virFirmware *virFirmwarePtr;
+
+struct _virFirmware {
+    char *name;
+    char *nvram;
+};
+
+
+void
+virFirmwareFreeList(virFirmwarePtr *firmwares, size_t nfirmwares);
+
+int
+virFirmwareParse(const char *str, virFirmwarePtr firmware)
+    ATTRIBUTE_NONNULL(2);
+
+int
+virFirmwareParseList(const char *list,
+                     virFirmwarePtr **firmwares,
+                     size_t *nfirmwares)
+    ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+
+#endif /* __VIR_FIRMWARE_H__ */
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index e1d0671..83ce0e5 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -128,7 +128,8 @@ fillQemuCaps(virDomainCapsPtr domCaps,
         goto cleanup;
 
     if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps,
-                                  cfg->loader, cfg->nloader) < 0)
+                                  cfg->firmwares,
+                                  cfg->nfirmwares) < 0)
         goto cleanup;
 
     /* The function above tries to query host's KVM & VFIO capabilities by
-- 
2.1.4




More information about the libvir-list mailing list