diff --git a/0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch b/0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch index a8563b5..cbff862 100644 --- a/0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch +++ b/0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch @@ -1,6 +1,6 @@ -From 28b27787c5bb545df3c178fef682151c45b66784 Mon Sep 17 00:00:00 2001 +From b2735463b886ac88027cec0ff1a4dbaa4f8be739 Mon Sep 17 00:00:00 2001 From: Martin Kletzander -Date: Mon, 8 Sep 2014 07:46:39 +0200 +Date: Sun, 7 Sep 2014 20:41:11 +0200 Subject: [PATCH] rpc: make daemon spawning a bit more intelligent This way it behaves more like the daemon itself does (acquiring a @@ -10,12 +10,13 @@ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=927369 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1138604 Signed-off-by: Martin Kletzander +(cherry picked from commit bd9ad91a4036649645fffb1598213339263478de) --- - src/rpc/virnetsocket.c | 57 ++++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 51 insertions(+), 6 deletions(-) + src/rpc/virnetsocket.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c -index 306c9ea..fa9ba99 100644 +index 306c9ea..5feccf6 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -51,9 +51,11 @@ @@ -41,7 +42,7 @@ index 306c9ea..fa9ba99 100644 virSocketAddr localAddr; virSocketAddr remoteAddr; -@@ -583,16 +588,45 @@ int virNetSocketNewConnectUNIX(const char *path, +@@ -583,16 +588,46 @@ int virNetSocketNewConnectUNIX(const char *path, goto error; } @@ -55,7 +56,8 @@ index 306c9ea..fa9ba99 100644 + if (virPidFileConstructPath(false, NULL, binname, &pidpath) < 0) + goto error; + -+ if ((pidfd = virPidFileAcquirePath(pidpath, false, getpid())) < 0) { ++ pidfd = virPidFileAcquirePath(pidpath, false, getpid()); ++ if (pidfd < 0) { + /* + * This can happen in a very rare case of two clients spawning two + * daemons at the same time, and the error in the logs that gets @@ -76,7 +78,7 @@ index 306c9ea..fa9ba99 100644 - * per-process, chmod() is racy and fchmod() has undefined - * behaviour on sockets according to POSIX, so it doesn't - * work outside Linux. -+ * We already even acquired the pidfile, so noone else should be using ++ * We already even acquired the pidfile, so no one else should be using + * @path right now. So we're OK to unlink it and paying attention to + * the return value makes no real sense here. Only if it's not an + * abstract socket, of course. @@ -91,19 +93,28 @@ index 306c9ea..fa9ba99 100644 */ if ((pid = virFork()) < 0) goto error; -@@ -612,8 +646,9 @@ int virNetSocketNewConnectUNIX(const char *path, +@@ -610,12 +645,16 @@ int virNetSocketNewConnectUNIX(const char *path, + + if (status != EXIT_SUCCESS) { /* - * OK, so the subprocces failed to bind() the socket. This may mean - * that another daemon was starting at the same time and succeeded +- * OK, so the subprocces failed to bind() the socket. This may mean +- * that another daemon was starting at the same time and succeeded - * with its bind(). So we'll try connecting again, but this time - * without spawning the daemon. -+ * with its bind() (even though it should not happen because we -+ * using a pidfile for the race). So we'll try connecting again, -+ * but this time without spawning the daemon. ++ * OK, so the child failed to bind() the socket. This may mean that ++ * another daemon was starting at the same time and succeeded with ++ * its bind() (even though it should not happen because we using a ++ * pidfile for the race). So we'll try connecting again, but this ++ * time without spawning the daemon. */ spawnDaemon = false; ++ virPidFileDeletePath(pidpath); ++ VIR_FORCE_CLOSE(pidfd); ++ VIR_FORCE_CLOSE(passfd); goto retry; -@@ -632,6 +667,12 @@ int virNetSocketNewConnectUNIX(const char *path, + } + +@@ -632,6 +671,12 @@ int virNetSocketNewConnectUNIX(const char *path, goto error; } @@ -116,11 +127,16 @@ index 306c9ea..fa9ba99 100644 if (virNetSocketForkDaemon(binary, passfd) < 0) goto error; } -@@ -648,8 +689,12 @@ int virNetSocketNewConnectUNIX(const char *path, +@@ -645,11 +690,17 @@ int virNetSocketNewConnectUNIX(const char *path, + if (!(*retsock = virNetSocketNew(&localAddr, &remoteAddr, true, fd, -1, 0))) + goto error; + ++ VIR_FREE(pidpath); ++ return 0; error: -+ if (pidfd > 0) ++ if (pidfd >= 0) + virPidFileDeletePath(pidpath); + VIR_FREE(pidpath); VIR_FORCE_CLOSE(fd); diff --git a/0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch b/0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch index 13fb17d..af15af4 100644 --- a/0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch +++ b/0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch @@ -1,4 +1,4 @@ -From 2950887a9e7800e0421dadb0b9c348adb087deca Mon Sep 17 00:00:00 2001 +From d437ccd8fef17c2bb119e98a034bdc56ff9425b2 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Mon, 15 Sep 2014 14:49:35 -0400 Subject: [PATCH] spec: Don't build wireshark on f21 (non upstream) diff --git a/0009-spec-Fix-preun-script-for-daemon.patch b/0009-spec-Fix-preun-script-for-daemon.patch index a273573..ec9d1c7 100644 --- a/0009-spec-Fix-preun-script-for-daemon.patch +++ b/0009-spec-Fix-preun-script-for-daemon.patch @@ -1,4 +1,4 @@ -From 09f0ff32b8925131c058de768751d3368f47a722 Mon Sep 17 00:00:00 2001 +From abb9c206877a937c2a509ec534c190b27c0b0e55 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 3 Sep 2014 10:51:14 +0200 Subject: [PATCH] spec: Fix preun script for daemon diff --git a/0010-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-t.patch b/0010-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-t.patch new file mode 100644 index 0000000..d83e534 --- /dev/null +++ b/0010-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-t.patch @@ -0,0 +1,98 @@ +From c414cb524bdbc3555a5332fe75b40f8cf3ded0f4 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Thu, 18 Sep 2014 15:17:29 +0200 +Subject: [PATCH] virSecuritySELinuxSetTapFDLabel: Temporarily revert to old + behavior + +https://bugzilla.redhat.com/show_bug.cgi?id=1141879 + +A long time ago I've implemented support for so called multiqueue +net. The idea was to let guest network traffic be processed by +multiple host CPUs and thus increasing performance. However, this +behavior is enabled by QEMU via special ioctl() iterated over the +all tap FDs passed in by libvirt. Unfortunately, SELinux comes in +and disallows the ioctl() call because the /dev/net/tun has label +system_u:object_r:tun_tap_device_t:s0 and 'attach_queue' ioctl() +is not allowed on tun_tap_device_t type. So after discussion with +a SELinux developer we've decided that the FDs passed to the QEMU +should be labelled with svirt_t type and SELinux policy will +allow the ioctl(). Therefore I've made a patch +(cf976d9dcf4e592261b14f03572) that does exactly this. The patch +was fixed then by a4431931393aeb1ac5893f121151fa3df4fde612 and +b635b7a1af0e64754016d758376f382470bc11e7. However, things are not +that easy - even though the API to label FD is called +(fsetfilecon_raw) the underlying file is labelled too! So +effectively we are mangling /dev/net/tun label. Yes, that broke +dozen of other application from openvpn, or boxes, to qemu +running other domains. + +The best solution would be if SELinux provides a way to label an +FD only, which could be then labeled when passed to the qemu. +However that's a long path to go and we should fix this +regression AQAP. So I went to talk to the SELinux developer again +and we agreed on temporary solution that: + +1) All the three patches are reverted +2) SELinux temporarily allows 'attach_queue' on the +tun_tap_device_t + +Signed-off-by: Michal Privoznik +(cherry picked from commit ba7468dbb13f552a9177d01ea8bad155f9877bc3) +--- + src/security/security_selinux.c | 34 ++++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index e8c13db..c078cab 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -2330,17 +2330,47 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, + } + + static int +-virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, ++virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr, + virDomainDefPtr def, + int fd) + { ++ struct stat buf; ++ security_context_t fcon = NULL; + virSecurityLabelDefPtr secdef; ++ char *str = NULL; ++ int rc = -1; + + secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME); + if (!secdef || !secdef->label) + return 0; + +- return virSecuritySELinuxFSetFilecon(fd, secdef->imagelabel); ++ if (fstat(fd, &buf) < 0) { ++ virReportSystemError(errno, _("cannot stat tap fd %d"), fd); ++ goto cleanup; ++ } ++ ++ if ((buf.st_mode & S_IFMT) != S_IFCHR) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("tap fd %d is not character device"), fd); ++ goto cleanup; ++ } ++ ++ if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("cannot lookup default selinux label for tap fd %d"), fd); ++ goto cleanup; ++ } ++ ++ if (!(str = virSecuritySELinuxContextAddRange(secdef->label, fcon))) { ++ goto cleanup; ++ } else { ++ rc = virSecuritySELinuxFSetFilecon(fd, str); ++ } ++ ++ cleanup: ++ freecon(fcon); ++ VIR_FREE(str); ++ return rc; + } + + static char * diff --git a/0011-conf-Extend-loader-and-introduce-nvram.patch b/0011-conf-Extend-loader-and-introduce-nvram.patch new file mode 100644 index 0000000..82bd6cd --- /dev/null +++ b/0011-conf-Extend-loader-and-introduce-nvram.patch @@ -0,0 +1,1296 @@ +From 589e1c627bcfe2d8f26c6cb9ea0c68e9b902a931 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Wed, 6 Aug 2014 13:18:53 +0200 +Subject: [PATCH] conf: Extend and introduce + +Up to now, users can configure BIOS via the element. With +the upcoming implementation of UEFI this is not enough as BIOS and +UEFI are conceptually different. For instance, while BIOS is ROM, UEFI +is programmable flash (although all writes to code section are +denied). Therefore we need new attribute @type which will +differentiate the two. Then, new attribute @readonly is introduced to +reflect the fact that some images are RO. + +Moreover, the OVMF (which is going to be used mostly), works in two +modes: +1) Code and UEFI variable store is mixed in one file. +2) Code and UEFI variable store is separated in two files + +The latter has advantage of updating the UEFI code without losing the +configuration. However, in order to represent the latter case we need +yet another XML element: . Currently, it has no additional +attributes, it's just a bare element containing path to the variable +store file. + +Signed-off-by: Michal Privoznik +Acked-by: Laszlo Ersek +Signed-off-by: Michal Privoznik +(cherry picked from commit 68bf13dbef8342eaee0bf57c73cebb60b7de11e8) +--- + docs/formatdomain.html.in | 19 ++++- + docs/schemas/domaincommon.rng | 21 ++++++ + src/conf/domain_conf.c | 87 +++++++++++++++++++++- + src/conf/domain_conf.h | 22 +++++- + src/libvirt_private.syms | 3 + + src/qemu/qemu_command.c | 5 +- + src/security/virt-aa-helper.c | 4 +- + src/vbox/vbox_common.c | 7 +- + src/xenapi/xenapi_driver.c | 3 +- + src/xenconfig/xen_common.c | 7 +- + src/xenconfig/xen_sxpr.c | 16 ++-- + tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml | 40 ++++++++++ + .../qemuxml2xmlout-pci-bridge-many-disks.xml | 2 +- + tests/qemuxml2xmltest.c | 2 + + tests/sexpr2xmldata/sexpr2xml-fv-autoport.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-empty-kernel.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-force-hpet.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-force-nohpet.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-net-ioemu.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-net-netfront.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml | 2 +- + .../sexpr2xml-fv-serial-dev-2-ports.xml | 2 +- + .../sexpr2xml-fv-serial-dev-2nd-port.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml | 2 +- + .../sexpr2xml-fv-serial-tcp-telnet.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-sound.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-utc.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv-v2.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-fv.xml | 2 +- + tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml | 2 +- + tests/xmconfigdata/test-escape-paths.xml | 2 +- + tests/xmconfigdata/test-fullvirt-force-hpet.xml | 2 +- + tests/xmconfigdata/test-fullvirt-force-nohpet.xml | 2 +- + tests/xmconfigdata/test-fullvirt-localtime.xml | 2 +- + tests/xmconfigdata/test-fullvirt-net-ioemu.xml | 2 +- + tests/xmconfigdata/test-fullvirt-net-netfront.xml | 2 +- + tests/xmconfigdata/test-fullvirt-new-cdrom.xml | 2 +- + tests/xmconfigdata/test-fullvirt-old-cdrom.xml | 2 +- + tests/xmconfigdata/test-fullvirt-parallel-tcp.xml | 2 +- + .../test-fullvirt-serial-dev-2-ports.xml | 2 +- + .../test-fullvirt-serial-dev-2nd-port.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-file.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-null.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-pipe.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-pty.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-stdio.xml | 2 +- + .../test-fullvirt-serial-tcp-telnet.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-tcp.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-udp.xml | 2 +- + tests/xmconfigdata/test-fullvirt-serial-unix.xml | 2 +- + tests/xmconfigdata/test-fullvirt-sound.xml | 2 +- + tests/xmconfigdata/test-fullvirt-usbmouse.xml | 2 +- + tests/xmconfigdata/test-fullvirt-usbtablet.xml | 2 +- + tests/xmconfigdata/test-fullvirt-utc.xml | 2 +- + tests/xmconfigdata/test-no-source-cdrom.xml | 2 +- + tests/xmconfigdata/test-pci-devs.xml | 2 +- + 69 files changed, 269 insertions(+), 79 deletions(-) + create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml + +diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in +index 94236dd..757035a 100644 +--- a/docs/formatdomain.html.in ++++ b/docs/formatdomain.html.in +@@ -102,7 +102,8 @@ + ... + <os> + <type>hvm</type> +- <loader>/usr/lib/xen/boot/hvmloader</loader> ++ <loader readonly='on' type='rom'>/usr/lib/xen/boot/hvmloader</loader> ++ <nvram>/var/lib/libvirt/nvram/guest_VARS.fd</nvram> + <boot dev='hd'/> + <boot dev='cdrom'/> + <bootmenu enable='yes' timeout='3000'/> +@@ -129,7 +130,21 @@ + used to assist the domain creation process. It is used by Xen + fully virtualized domains as well as setting the QEMU BIOS file + path for QEMU/KVM domains. Xen since 0.1.0, +- QEMU/KVM since 0.9.12 ++ QEMU/KVM since 0.9.12 Then, since ++ 1.2.8 it's possible for the element to have two ++ optional attributes: readonly (accepted values are ++ yes and no) to reflect the fact that the ++ image should be writable or read-only. The second attribute ++ type accepts values rom and ++ pflash. It tells the hypervisor where in the guest ++ memory the file should be mapped. For instance, if the loader ++ path points to an UEFI image, type should be ++ pflash. ++
nvram
++
Some UEFI firmwares may want to use a non-volatile memory to store ++ some variables. In the host, this is represented as a file and the ++ path to the file is stored in this element. Since ++ 1.2.8
+
boot
+
The dev attribute takes one of the values "fd", "hd", + "cdrom" or "network" and is used to specify the next boot device +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index cedceae..5d9c21c 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -242,6 +242,27 @@ + + + ++ ++ ++ ++ yes ++ no ++ ++ ++ ++ ++ ++ ++ rom ++ pflash ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 53ef694..6ee5c17 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -777,6 +777,11 @@ VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST, + "abort", + "pivot") + ++VIR_ENUM_IMPL(virDomainLoader, ++ VIR_DOMAIN_LOADER_TYPE_LAST, ++ "rom", ++ "pflash") ++ + /* Internal mapping: subset of block job types that can be present in + * XML (remaining types are not two-phase). */ + VIR_ENUM_DECL(virDomainBlockJob) +@@ -2010,6 +2015,17 @@ virDomainPanicDefFree(virDomainPanicDefPtr panic) + VIR_FREE(panic); + } + ++void ++virDomainLoaderDefFree(virDomainLoaderDefPtr loader) ++{ ++ if (!loader) ++ return; ++ ++ VIR_FREE(loader->path); ++ VIR_FREE(loader->nvram); ++ VIR_FREE(loader); ++} ++ + void virDomainDefFree(virDomainDefPtr def) + { + size_t i; +@@ -2115,7 +2131,7 @@ void virDomainDefFree(virDomainDefPtr def) + VIR_FREE(def->os.cmdline); + VIR_FREE(def->os.dtb); + VIR_FREE(def->os.root); +- VIR_FREE(def->os.loader); ++ virDomainLoaderDefFree(def->os.loader); + VIR_FREE(def->os.bootloader); + VIR_FREE(def->os.bootloaderArgs); + +@@ -11661,6 +11677,42 @@ virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def) + return 0; + } + ++static int ++virDomainLoaderDefParseXML(xmlNodePtr node, ++ virDomainLoaderDefPtr loader) ++{ ++ int ret = -1; ++ char *readonly_str = NULL; ++ char *type_str = NULL; ++ ++ readonly_str = virXMLPropString(node, "readonly"); ++ type_str = virXMLPropString(node, "type"); ++ loader->path = (char *) xmlNodeGetContent(node); ++ ++ if (readonly_str && ++ (loader->readonly = virTristateBoolTypeFromString(readonly_str)) <= 0) { ++ virReportError(VIR_ERR_XML_DETAIL, ++ _("unknown readonly value: %s"), readonly_str); ++ goto cleanup; ++ } ++ ++ if (type_str) { ++ int type; ++ if ((type = virDomainLoaderTypeFromString(type_str)) < 0) { ++ virReportError(VIR_ERR_XML_DETAIL, ++ _("unknown type value: %s"), type_str); ++ goto cleanup; ++ } ++ loader->type = type; ++ } ++ ++ ret = 0; ++ cleanup: ++ VIR_FREE(readonly_str); ++ VIR_FREE(type_str); ++ return ret; ++} ++ + static virDomainDefPtr + virDomainDefParseXML(xmlDocPtr xml, + xmlNodePtr root, +@@ -12701,12 +12753,22 @@ virDomainDefParseXML(xmlDocPtr xml, + if (STREQ(def->os.type, "xen") || + STREQ(def->os.type, "hvm") || + STREQ(def->os.type, "uml")) { ++ xmlNodePtr loader_node; ++ + def->os.kernel = virXPathString("string(./os/kernel[1])", ctxt); + def->os.initrd = virXPathString("string(./os/initrd[1])", ctxt); + def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt); + def->os.dtb = virXPathString("string(./os/dtb[1])", ctxt); + def->os.root = virXPathString("string(./os/root[1])", ctxt); +- def->os.loader = virXPathString("string(./os/loader[1])", ctxt); ++ if ((loader_node = virXPathNode("./os/loader[1]", ctxt))) { ++ if (VIR_ALLOC(def->os.loader) < 0) ++ goto error; ++ ++ if (virDomainLoaderDefParseXML(loader_node, def->os.loader) < 0) ++ goto error; ++ ++ def->os.loader->nvram = virXPathString("string(./os/nvram[1])", ctxt); ++ } + } + + if (STREQ(def->os.type, "hvm")) { +@@ -17789,6 +17851,23 @@ virDomainHugepagesFormat(virBufferPtr buf, + virBufferAddLit(buf, "\n"); + } + ++static void ++virDomainLoaderDefFormat(virBufferPtr buf, ++ virDomainLoaderDefPtr loader) ++{ ++ const char *readonly = virTristateBoolTypeToString(loader->readonly); ++ const char *type = virDomainLoaderTypeToString(loader->type); ++ ++ virBufferAddLit(buf, "readonly) ++ virBufferAsprintf(buf, " readonly='%s'", readonly); ++ ++ virBufferAsprintf(buf, " type='%s'>", type); ++ ++ virBufferEscapeString(buf, "%s\n", loader->path); ++ virBufferEscapeString(buf, "%s\n", loader->nvram); ++} + + static bool + virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def) +@@ -18109,8 +18188,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, + for (i = 0; def->os.initargv && def->os.initargv[i]; i++) + virBufferEscapeString(buf, "%s\n", + def->os.initargv[i]); +- virBufferEscapeString(buf, "%s\n", +- def->os.loader); ++ if (def->os.loader) ++ virDomainLoaderDefFormat(buf, def->os.loader); + virBufferEscapeString(buf, "%s\n", + def->os.kernel); + virBufferEscapeString(buf, "%s\n", +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 9586c3b..c97a10c 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -1628,6 +1628,26 @@ struct _virDomainBIOSDef { + int rt_delay; + }; + ++typedef enum { ++ VIR_DOMAIN_LOADER_TYPE_ROM = 0, ++ VIR_DOMAIN_LOADER_TYPE_PFLASH, ++ ++ VIR_DOMAIN_LOADER_TYPE_LAST ++} virDomainLoader; ++ ++VIR_ENUM_DECL(virDomainLoader) ++ ++typedef struct _virDomainLoaderDef virDomainLoaderDef; ++typedef virDomainLoaderDef *virDomainLoaderDefPtr; ++struct _virDomainLoaderDef { ++ char *path; ++ int readonly; /* enum virTristateBool */ ++ virDomainLoader type; ++ char *nvram; /* path to non-volatile RAM */ ++}; ++ ++void virDomainLoaderDefFree(virDomainLoaderDefPtr loader); ++ + /* Operating system configuration data & machine / arch */ + typedef struct _virDomainOSDef virDomainOSDef; + typedef virDomainOSDef *virDomainOSDefPtr; +@@ -1647,7 +1667,7 @@ struct _virDomainOSDef { + char *cmdline; + char *dtb; + char *root; +- char *loader; ++ virDomainLoaderDefPtr loader; + char *bootloader; + char *bootloaderArgs; + int smbios_mode; +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index f8d9b95..18cf0c2 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -313,6 +313,9 @@ virDomainLifecycleTypeFromString; + virDomainLifecycleTypeToString; + virDomainListFree; + virDomainLiveConfigHelperMethod; ++virDomainLoaderDefFree; ++virDomainLoaderTypeFromString; ++virDomainLoaderTypeToString; + virDomainLockFailureTypeFromString; + virDomainLockFailureTypeToString; + virDomainMemballoonModelTypeFromString; +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index 2184caa..3cb2e0b 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -7527,7 +7527,7 @@ qemuBuildCommandLine(virConnectPtr conn, + + if (def->os.loader) { + virCommandAddArg(cmd, "-bios"); +- virCommandAddArg(cmd, def->os.loader); ++ virCommandAddArg(cmd, def->os.loader->path); + } + + /* Set '-m MB' based on maxmem, because the lower 'memory' limit +@@ -11347,7 +11347,8 @@ qemuParseCommandLine(virCapsPtr qemuCaps, + goto error; + } else if (STREQ(arg, "-bios")) { + WANT_VALUE(); +- if (VIR_STRDUP(def->os.loader, val) < 0) ++ if (VIR_ALLOC(def->os.loader) < 0 || ++ VIR_STRDUP(def->os.loader->path, val) < 0) + goto error; + } else if (STREQ(arg, "-initrd")) { + WANT_VALUE(); +diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c +index a0b104c..311ce3b 100644 +--- a/src/security/virt-aa-helper.c ++++ b/src/security/virt-aa-helper.c +@@ -1006,8 +1006,8 @@ get_files(vahControl * ctl) + if (vah_add_file(&buf, ctl->def->os.dtb, "r") != 0) + goto cleanup; + +- if (ctl->def->os.loader && ctl->def->os.loader) +- if (vah_add_file(&buf, ctl->def->os.loader, "r") != 0) ++ if (ctl->def->os.loader && ctl->def->os.loader->path) ++ if (vah_add_file(&buf, ctl->def->os.loader->path, "r") != 0) + goto cleanup; + + for (i = 0; i < ctl->def->ngraphics; i++) { +diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c +index b186ea8..6f56c59 100644 +--- a/src/vbox/vbox_common.c ++++ b/src/vbox/vbox_common.c +@@ -988,7 +988,12 @@ vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data, + VIR_DEBUG("def->os.initrd %s", def->os.initrd); + VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); + VIR_DEBUG("def->os.root %s", def->os.root); +- VIR_DEBUG("def->os.loader %s", def->os.loader); ++ if (def->os.loader) { ++ VIR_DEBUG("def->os.loader->path %s", def->os.loader->path); ++ VIR_DEBUG("def->os.loader->readonly %d", def->os.loader->readonly); ++ VIR_DEBUG("def->os.loader->type %d", def->os.loader->type); ++ VIR_DEBUG("def->os.loader->nvram %s", def->os.loader->nvram); ++ } + VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); + VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); + +diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c +index 50331c9..a6eaccc 100644 +--- a/src/xenapi/xenapi_driver.c ++++ b/src/xenapi/xenapi_driver.c +@@ -1427,7 +1427,8 @@ xenapiDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) + VIR_FREE(boot_policy); + goto error; + } +- if (VIR_STRDUP(defPtr->os.loader, "pygrub") < 0) { ++ if (VIR_ALLOC(defPtr->os.loader) < 0 || ++ VIR_STRDUP(defPtr->os.loader->path, "pygrub") < 0) { + VIR_FREE(boot_policy); + goto error; + } +diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c +index 9beaf6c..abd77b5 100644 +--- a/src/xenconfig/xen_common.c ++++ b/src/xenconfig/xen_common.c +@@ -1065,7 +1065,8 @@ xenParseOS(virConfPtr conf, virDomainDefPtr def) + if (STREQ(def->os.type, "hvm")) { + const char *boot; + +- if (xenConfigCopyString(conf, "kernel", &def->os.loader) < 0) ++ if (VIR_ALLOC(def->os.loader) < 0 || ++ xenConfigCopyString(conf, "kernel", &def->os.loader->path) < 0) + return -1; + + if (xenConfigGetString(conf, "boot", &boot, "c") < 0) +@@ -1740,8 +1741,8 @@ xenFormatOS(virConfPtr conf, virDomainDefPtr def) + if (xenXMConfigSetString(conf, "builder", "hvm") < 0) + return -1; + +- if (def->os.loader && +- xenXMConfigSetString(conf, "kernel", def->os.loader) < 0) ++ if (def->os.loader && def->os.loader->path && ++ xenXMConfigSetString(conf, "kernel", def->os.loader->path) < 0) + return -1; + + for (i = 0; i < def->os.nBootDevs; i++) { +diff --git a/src/xenconfig/xen_sxpr.c b/src/xenconfig/xen_sxpr.c +index ff81c36..e8b9f59 100644 +--- a/src/xenconfig/xen_sxpr.c ++++ b/src/xenconfig/xen_sxpr.c +@@ -93,13 +93,15 @@ xenParseSxprOS(const struct sexpr *node, + int hvm) + { + if (hvm) { +- if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0) ++ if (VIR_ALLOC(def->os.loader) < 0) + goto error; +- if (def->os.loader == NULL) { +- if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0) ++ if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader->path) < 0) ++ goto error; ++ if (def->os.loader->path == NULL) { ++ if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader->path) < 0) + goto error; + +- if (def->os.loader == NULL) { ++ if (def->os.loader->path == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("domain information incomplete, missing HVM loader")); + return -1; +@@ -128,7 +130,7 @@ xenParseSxprOS(const struct sexpr *node, + /* If HVM kenrel == loader, then old xend, so kill off kernel */ + if (hvm && + def->os.kernel && +- STREQ(def->os.kernel, def->os.loader)) { ++ STREQ(def->os.kernel, def->os.loader->path)) { + VIR_FREE(def->os.kernel); + } + /* Drop kernel argument that has no value */ +@@ -2279,9 +2281,9 @@ xenFormatSxpr(virConnectPtr conn, + if (hvm) { + char bootorder[VIR_DOMAIN_BOOT_LAST+1]; + if (def->os.kernel) +- virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader); ++ virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader->path); + else +- virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader); ++ virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader->path); + + virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); + if (def->vcpus < def->maxvcpus) +diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml +new file mode 100644 +index 0000000..d8270b1 +--- /dev/null ++++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml +@@ -0,0 +1,40 @@ ++ ++ test-bios ++ 362d1fc1-df7d-193e-5c18-49a71bd1da66 ++ 1048576 ++ 1048576 ++ 1 ++ ++ hvm ++ /usr/share/OVMF/OVMF_CODE.fd ++ /usr/share/OVMF/OVMF_VARS.fd ++ ++ ++ ++ ++ ++ ++ ++ destroy ++ restart ++ restart ++ ++ /usr/bin/qemu ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml +index d469b8b..d49f5f4 100644 +--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml ++++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pci-bridge-many-disks.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/share/seabios/bios.bin ++ /usr/share/seabios/bios.bin + + + +diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c +index b4ab671..1835fe6 100644 +--- a/tests/qemuxml2xmltest.c ++++ b/tests/qemuxml2xmltest.c +@@ -395,6 +395,8 @@ mymain(void) + DO_TEST_DIFFERENT("numatune-memnode"); + DO_TEST("numatune-memnode-no-memory"); + ++ DO_TEST("bios-nvram"); ++ + virObjectUnref(driver.caps); + virObjectUnref(driver.xmlopt); + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-autoport.xml b/tests/sexpr2xmldata/sexpr2xml-fv-autoport.xml +index 69fe9ef..761952c 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-autoport.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-autoport.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-empty-kernel.xml b/tests/sexpr2xmldata/sexpr2xml-fv-empty-kernel.xml +index 3c3147d..2898098 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-empty-kernel.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-empty-kernel.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-force-hpet.xml b/tests/sexpr2xmldata/sexpr2xml-fv-force-hpet.xml +index 716f16b..a0fe30d 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-force-hpet.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-force-hpet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-force-nohpet.xml b/tests/sexpr2xmldata/sexpr2xml-fv-force-nohpet.xml +index 3dd648b..851797d 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-force-nohpet.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-force-nohpet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml b/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml +index 29c1335..09cfe19 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-kernel.xml +@@ -6,7 +6,7 @@ + 2 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + /var/lib/xen/vmlinuz.2Dn2YT + /var/lib/xen/initrd.img.0u-Vhq + method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml b/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml +index 9c59644..44c0f61 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-legacy-vfb.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml b/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml +index 67b0b95..29007f0 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-net-ioemu.xml b/tests/sexpr2xmldata/sexpr2xml-fv-net-ioemu.xml +index 86b32e9..3dbc999 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-net-ioemu.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-net-ioemu.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-net-netfront.xml b/tests/sexpr2xmldata/sexpr2xml-fv-net-netfront.xml +index ed7da80..d96350e 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-net-netfront.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-net-netfront.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml b/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml +index ed3fde6..7ad377c 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-parallel-tcp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml +index 7f5a729..adba6cb 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2-ports.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2nd-port.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2nd-port.xml +index 10f84dc..b6c3601 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2nd-port.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-dev-2nd-port.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml +index a3fd231..dabe679 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-file.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml +index b3f77c9..fb19d74 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-null.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml +index e217161..5aa425b 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pipe.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml +index 3ad2264..3c2ca21 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-pty.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml +index 001df56..160edbd 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-stdio.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml +index c2496fd..4396efc 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp-telnet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml +index 6dc047e..3d17b58 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-tcp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml +index 7ccaeac..fc3d457 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-udp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml b/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml +index b5ad413..14b54f1 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-serial-unix.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml +index 7183e79..912df56 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound-all.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml b/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml +index 7183e79..912df56 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-sound.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml b/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml +index ae90e33..19eac3b 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml b/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml +index f81c47a..40ac8a9 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml b/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml +index c783d93..97f2beb 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml b/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml +index bd3b107..493d1b5 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-fv.xml b/tests/sexpr2xmldata/sexpr2xml-fv.xml +index c783d93..97f2beb 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-fv.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-fv.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml b/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml +index 00d18ce..a3cd7be 100644 +--- a/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml ++++ b/tests/sexpr2xmldata/sexpr2xml-no-source-cdrom.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-escape-paths.xml b/tests/xmconfigdata/test-escape-paths.xml +index de3a7e2..623eaa1 100644 +--- a/tests/xmconfigdata/test-escape-paths.xml ++++ b/tests/xmconfigdata/test-escape-paths.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader&test ++ /usr/lib/xen/boot/hvmloader&test + + + +diff --git a/tests/xmconfigdata/test-fullvirt-force-hpet.xml b/tests/xmconfigdata/test-fullvirt-force-hpet.xml +index 75f8724..57a6531 100644 +--- a/tests/xmconfigdata/test-fullvirt-force-hpet.xml ++++ b/tests/xmconfigdata/test-fullvirt-force-hpet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-force-nohpet.xml b/tests/xmconfigdata/test-fullvirt-force-nohpet.xml +index e5741b6..f6ebcf6 100644 +--- a/tests/xmconfigdata/test-fullvirt-force-nohpet.xml ++++ b/tests/xmconfigdata/test-fullvirt-force-nohpet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-localtime.xml b/tests/xmconfigdata/test-fullvirt-localtime.xml +index 8b97e5b..36ab389 100644 +--- a/tests/xmconfigdata/test-fullvirt-localtime.xml ++++ b/tests/xmconfigdata/test-fullvirt-localtime.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-net-ioemu.xml b/tests/xmconfigdata/test-fullvirt-net-ioemu.xml +index f22c085..3618bae 100644 +--- a/tests/xmconfigdata/test-fullvirt-net-ioemu.xml ++++ b/tests/xmconfigdata/test-fullvirt-net-ioemu.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-net-netfront.xml b/tests/xmconfigdata/test-fullvirt-net-netfront.xml +index 177bb6a..6a2a439 100644 +--- a/tests/xmconfigdata/test-fullvirt-net-netfront.xml ++++ b/tests/xmconfigdata/test-fullvirt-net-netfront.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml +index f22c085..3618bae 100644 +--- a/tests/xmconfigdata/test-fullvirt-new-cdrom.xml ++++ b/tests/xmconfigdata/test-fullvirt-new-cdrom.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml +index a592630..7d6014d 100644 +--- a/tests/xmconfigdata/test-fullvirt-old-cdrom.xml ++++ b/tests/xmconfigdata/test-fullvirt-old-cdrom.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml +index 738e5ab..9b1fd26 100644 +--- a/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml ++++ b/tests/xmconfigdata/test-fullvirt-parallel-tcp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml +index 753831a..a64d40b 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2-ports.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml b/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml +index 1a55080..ce2cddb 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-dev-2nd-port.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-file.xml b/tests/xmconfigdata/test-fullvirt-serial-file.xml +index 0d2ac79..36883de 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-file.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-file.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-null.xml b/tests/xmconfigdata/test-fullvirt-serial-null.xml +index d4b4ae9..982f9d6 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-null.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-null.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml +index 6596dfc..82a1d9b 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-pipe.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-pipe.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-pty.xml b/tests/xmconfigdata/test-fullvirt-serial-pty.xml +index 6c55abb..56ccbea 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-pty.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-pty.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml +index 461f143..e2e9330 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-stdio.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-stdio.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml +index d2fa7bf..d68d77c 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-tcp-telnet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml +index 60ab8bd..aa3ed5c 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-tcp.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-tcp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-udp.xml b/tests/xmconfigdata/test-fullvirt-serial-udp.xml +index 6c21cd2..256c722 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-udp.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-udp.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-serial-unix.xml b/tests/xmconfigdata/test-fullvirt-serial-unix.xml +index f21534e..235c8d4 100644 +--- a/tests/xmconfigdata/test-fullvirt-serial-unix.xml ++++ b/tests/xmconfigdata/test-fullvirt-serial-unix.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-sound.xml b/tests/xmconfigdata/test-fullvirt-sound.xml +index f09c16d..1429d10 100644 +--- a/tests/xmconfigdata/test-fullvirt-sound.xml ++++ b/tests/xmconfigdata/test-fullvirt-sound.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-usbmouse.xml b/tests/xmconfigdata/test-fullvirt-usbmouse.xml +index 18a7ff0..25857f1 100644 +--- a/tests/xmconfigdata/test-fullvirt-usbmouse.xml ++++ b/tests/xmconfigdata/test-fullvirt-usbmouse.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-usbtablet.xml b/tests/xmconfigdata/test-fullvirt-usbtablet.xml +index 5cbb007..31b1176 100644 +--- a/tests/xmconfigdata/test-fullvirt-usbtablet.xml ++++ b/tests/xmconfigdata/test-fullvirt-usbtablet.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-fullvirt-utc.xml b/tests/xmconfigdata/test-fullvirt-utc.xml +index f22c085..3618bae 100644 +--- a/tests/xmconfigdata/test-fullvirt-utc.xml ++++ b/tests/xmconfigdata/test-fullvirt-utc.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-no-source-cdrom.xml b/tests/xmconfigdata/test-no-source-cdrom.xml +index 2a457b2..74f1be1 100644 +--- a/tests/xmconfigdata/test-no-source-cdrom.xml ++++ b/tests/xmconfigdata/test-no-source-cdrom.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + +diff --git a/tests/xmconfigdata/test-pci-devs.xml b/tests/xmconfigdata/test-pci-devs.xml +index f828056..1911734 100644 +--- a/tests/xmconfigdata/test-pci-devs.xml ++++ b/tests/xmconfigdata/test-pci-devs.xml +@@ -6,7 +6,7 @@ + 1 + + hvm +- /usr/lib/xen/boot/hvmloader ++ /usr/lib/xen/boot/hvmloader + + + diff --git a/0012-qemu-Implement-extended-loader-and-nvram.patch b/0012-qemu-Implement-extended-loader-and-nvram.patch new file mode 100644 index 0000000..c5e57f3 --- /dev/null +++ b/0012-qemu-Implement-extended-loader-and-nvram.patch @@ -0,0 +1,222 @@ +From ac0859aae7162255848effdc560368266845dfce Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Thu, 7 Aug 2014 13:50:00 +0200 +Subject: [PATCH] qemu: Implement extended loader and nvram + +QEMU now supports UEFI with the following command line: + + -drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \ + -drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \ + +where the first line reflects and the second one . +Moreover, these two lines obsolete the -bios argument. + +Note that UEFI is unusable without ACPI. This is handled properly now. +Among with this extension, the variable file is expected to be +writable and hence we need security drivers to label it. + +Signed-off-by: Michal Privoznik +Acked-by: Laszlo Ersek +(cherry picked from commit 542899168c382610dbad9a597d27ef3d7c699f68) +--- + src/qemu/qemu_command.c | 94 +++++++++++++++++++++- + src/security/security_dac.c | 8 ++ + src/security/security_selinux.c | 8 ++ + .../qemuxml2argvdata/qemuxml2argv-bios-nvram.args | 10 +++ + tests/qemuxml2argvtest.c | 2 + + 5 files changed, 118 insertions(+), 4 deletions(-) + create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index 3cb2e0b..718533b 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -7370,6 +7370,94 @@ qemuBuildChrDeviceCommandLine(virCommandPtr cmd, + return 0; + } + ++static int ++qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, ++ virDomainDefPtr def, ++ virQEMUCapsPtr qemuCaps) ++{ ++ int ret = -1; ++ virDomainLoaderDefPtr loader = def->os.loader; ++ virBuffer buf = VIR_BUFFER_INITIALIZER; ++ int unit = 0; ++ ++ if (!loader) ++ return 0; ++ ++ switch ((virDomainLoader) loader->type) { ++ case VIR_DOMAIN_LOADER_TYPE_ROM: ++ virCommandAddArg(cmd, "-bios"); ++ virCommandAddArg(cmd, loader->path); ++ break; ++ ++ case VIR_DOMAIN_LOADER_TYPE_PFLASH: ++ /* UEFI is supported only for x86_64 currently */ ++ if (def->os.arch != VIR_ARCH_X86_64) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("pflash is not supported for %s guest architecture"), ++ virArchToString(def->os.arch)); ++ goto cleanup; ++ } ++ ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("this QEMU binary doesn't support -drive")); ++ goto cleanup; ++ } ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("this QEMU binary doesn't support passing " ++ "drive format")); ++ goto cleanup; ++ } ++ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI) && ++ def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("ACPI must be enabled in order to use UEFI")); ++ goto cleanup; ++ } ++ ++ virBufferAsprintf(&buf, ++ "file=%s,if=pflash,format=raw,unit=%d", ++ loader->path, unit); ++ unit++; ++ ++ if (loader->readonly) { ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("this qemu doesn't support passing " ++ "readonly attribute")); ++ goto cleanup; ++ } ++ ++ virBufferAsprintf(&buf, ",readonly=%s", ++ virTristateSwitchTypeToString(loader->readonly)); ++ } ++ ++ virCommandAddArg(cmd, "-drive"); ++ virCommandAddArgBuffer(cmd, &buf); ++ ++ if (loader->nvram) { ++ virBufferFreeAndReset(&buf); ++ virBufferAsprintf(&buf, ++ "file=%s,if=pflash,format=raw,unit=%d", ++ loader->nvram, unit); ++ ++ virCommandAddArg(cmd, "-drive"); ++ virCommandAddArgBuffer(cmd, &buf); ++ } ++ break; ++ ++ case VIR_DOMAIN_LOADER_TYPE_LAST: ++ /* nada */ ++ break; ++ } ++ ++ ret = 0; ++ cleanup: ++ virBufferFreeAndReset(&buf); ++ return ret; ++} ++ + qemuBuildCommandLineCallbacks buildCommandLineCallbacks = { + .qemuGetSCSIDeviceSgName = virSCSIDeviceGetSgName, + }; +@@ -7525,10 +7613,8 @@ qemuBuildCommandLine(virConnectPtr conn, + virCommandAddArg(cmd, "-enable-nesting"); + } + +- if (def->os.loader) { +- virCommandAddArg(cmd, "-bios"); +- virCommandAddArg(cmd, def->os.loader->path); +- } ++ if (qemuBuildDomainLoaderCommandLine(cmd, def, qemuCaps) < 0) ++ goto error; + + /* Set '-m MB' based on maxmem, because the lower 'memory' limit + * is set post-startup using the balloon driver. If balloon driver +diff --git a/src/security/security_dac.c b/src/security/security_dac.c +index e62828e..e398d2c 100644 +--- a/src/security/security_dac.c ++++ b/src/security/security_dac.c +@@ -960,6 +960,10 @@ virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr, + rc = -1; + } + ++ if (def->os.loader && def->os.loader->nvram && ++ virSecurityDACRestoreSecurityFileLabel(def->os.loader->nvram) < 0) ++ rc = -1; ++ + if (def->os.kernel && + virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0) + rc = -1; +@@ -1036,6 +1040,10 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr, + if (virSecurityDACGetImageIds(secdef, priv, &user, &group)) + return -1; + ++ if (def->os.loader && def->os.loader->nvram && ++ virSecurityDACSetOwnership(def->os.loader->nvram, user, group) < 0) ++ return -1; ++ + if (def->os.kernel && + virSecurityDACSetOwnership(def->os.kernel, user, group) < 0) + return -1; +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index c078cab..a409c19 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -1911,6 +1911,10 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr, + mgr) < 0) + rc = -1; + ++ if (def->os.loader && def->os.loader->nvram && ++ virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.loader->nvram) < 0) ++ rc = -1; ++ + if (def->os.kernel && + virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.kernel) < 0) + rc = -1; +@@ -2294,6 +2298,10 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, + mgr) < 0) + return -1; + ++ if (def->os.loader && def->os.loader->nvram && ++ virSecuritySELinuxSetFilecon(def->os.loader->nvram, data->content_context) < 0) ++ return -1; ++ + if (def->os.kernel && + virSecuritySELinuxSetFilecon(def->os.kernel, data->content_context) < 0) + return -1; +diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args +new file mode 100644 +index 0000000..b51e8f3 +--- /dev/null ++++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args +@@ -0,0 +1,10 @@ ++LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ ++/usr/bin/qemu -S -M pc \ ++-drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \ ++-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \ ++-m 1024 -smp 1 -nographic -nodefaults \ ++-monitor unix:/tmp/test-monitor,server,nowait -boot c -usb \ ++-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0,format=raw \ ++-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \ ++-serial pty -device usb-tablet,id=input0 \ ++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 +diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c +index 3feb2fe..5c28253 100644 +--- a/tests/qemuxml2argvtest.c ++++ b/tests/qemuxml2argvtest.c +@@ -642,6 +642,8 @@ mymain(void) + DO_TEST_FAILURE("reboot-timeout-enabled", NONE); + + DO_TEST("bios", QEMU_CAPS_DEVICE, QEMU_CAPS_SGA); ++ DO_TEST("bios-nvram", QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, ++ QEMU_CAPS_DRIVE_FORMAT, QEMU_CAPS_DRIVE_READONLY); + DO_TEST("clock-utc", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE); + DO_TEST("clock-localtime", NONE); + DO_TEST("clock-localtime-basis-localtime", QEMU_CAPS_RTC); diff --git a/0013-qemu-Automatically-create-NVRAM-store.patch b/0013-qemu-Automatically-create-NVRAM-store.patch new file mode 100644 index 0000000..21ca6ff --- /dev/null +++ b/0013-qemu-Automatically-create-NVRAM-store.patch @@ -0,0 +1,579 @@ +From e2354416fdccb9649f080cdf912c5dc16d0eb578 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Thu, 7 Aug 2014 16:59:21 +0200 +Subject: [PATCH] qemu: Automatically create NVRAM store + +When using split UEFI image, it may come handy if libvirt manages per +domain _VARS file automatically. While the _CODE file is RO and can be +shared among multiple domains, you certainly don't want to do that on +the _VARS file. This latter one needs to be per domain. So at the +domain startup process, if it's determined that domain needs _VARS +file it's copied from this master _VARS file. The location of the +master file is configurable in qemu.conf. + +Temporary, on per domain basis the location of master NVRAM file can +be overridden by this @template attribute I'm inventing to the + element. All it does is holding path to the master NVRAM file +from which local copy is created. If that's the case, the map in +qemu.conf is not consulted. + +Signed-off-by: Michal Privoznik +Acked-by: Laszlo Ersek +(cherry picked from commit 742b08e30fd503bc992e864828cbabd7e6a099ec) +--- + docs/formatdomain.html.in | 11 +- + docs/schemas/domaincommon.rng | 9 +- + libvirt.spec.in | 2 + + src/Makefile.am | 1 + + src/conf/domain_conf.c | 11 +- + src/conf/domain_conf.h | 1 + + src/qemu/libvirtd_qemu.aug | 3 + + src/qemu/qemu.conf | 14 +++ + src/qemu/qemu_conf.c | 94 ++++++++++++++ + src/qemu/qemu_conf.h | 5 + + src/qemu/qemu_process.c | 137 +++++++++++++++++++++ + src/qemu/test_libvirtd_qemu.aug.in | 3 + + tests/domainschemadata/domain-bios-nvram-empty.xml | 40 ++++++ + 13 files changed, 325 insertions(+), 6 deletions(-) + create mode 100644 tests/domainschemadata/domain-bios-nvram-empty.xml + +diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in +index 757035a..a2ea758 100644 +--- a/docs/formatdomain.html.in ++++ b/docs/formatdomain.html.in +@@ -103,7 +103,7 @@ + <os> + <type>hvm</type> + <loader readonly='on' type='rom'>/usr/lib/xen/boot/hvmloader</loader> +- <nvram>/var/lib/libvirt/nvram/guest_VARS.fd</nvram> ++ <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/nvram/guest_VARS.fd</nvram> + <boot dev='hd'/> + <boot dev='cdrom'/> + <bootmenu enable='yes' timeout='3000'/> +@@ -142,9 +142,12 @@ + pflash.
+
nvram
+
Some UEFI firmwares may want to use a non-volatile memory to store +- some variables. In the host, this is represented as a file and the +- path to the file is stored in this element. Since +- 1.2.8
++ some variables. In the host, this is represented as a file and the path ++ to the file is stored in this element. Moreover, when the domain is ++ started up libvirt copies so called master NVRAM store file defined ++ in qemu.conf. If needed, the template ++ attribute can be used to per domain override map of master NVRAM stores ++ from the config file. Since 1.2.8 +
boot
+
The dev attribute takes one of the values "fd", "hd", + "cdrom" or "network" and is used to specify the next boot device +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index 5d9c21c..6ae940a 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -263,7 +263,14 @@ + + + +- ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/libvirt.spec.in b/libvirt.spec.in +index 6129f00..935b8c8 100644 +--- a/libvirt.spec.in ++++ b/libvirt.spec.in +@@ -1970,6 +1970,7 @@ exit 0 + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/ ++%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/ + %{_datadir}/augeas/lenses/libvirtd_qemu.aug + %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug +@@ -2072,6 +2073,7 @@ exit 0 + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/ ++%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/ + %{_datadir}/augeas/lenses/libvirtd_qemu.aug + %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug +diff --git a/src/Makefile.am b/src/Makefile.am +index 46e411e..fa741a8 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -2679,6 +2679,7 @@ endif WITH_SANLOCK + if WITH_QEMU + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu/channel/target" ++ $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu/nvram" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/qemu" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/cache/libvirt/qemu" + $(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/qemu" +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 6ee5c17..84f5f1d 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -2023,6 +2023,7 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) + + VIR_FREE(loader->path); + VIR_FREE(loader->nvram); ++ VIR_FREE(loader->templt); + VIR_FREE(loader); + } + +@@ -12768,6 +12769,7 @@ virDomainDefParseXML(xmlDocPtr xml, + goto error; + + def->os.loader->nvram = virXPathString("string(./os/nvram[1])", ctxt); ++ def->os.loader->templt = virXPathString("string(./os/nvram[1]/@template)", ctxt); + } + } + +@@ -17866,7 +17868,14 @@ virDomainLoaderDefFormat(virBufferPtr buf, + virBufferAsprintf(buf, " type='%s'>", type); + + virBufferEscapeString(buf, "%s\n", loader->path); +- virBufferEscapeString(buf, "%s\n", loader->nvram); ++ if (loader->nvram || loader->templt) { ++ virBufferAddLit(buf, "templt); ++ if (loader->nvram) ++ virBufferEscapeString(buf, ">%s\n", loader->nvram); ++ else ++ virBufferAddLit(buf, "/>\n"); ++ } + } + + static bool +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index c97a10c..3316fb6 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -1644,6 +1644,7 @@ struct _virDomainLoaderDef { + int readonly; /* enum virTristateBool */ + virDomainLoader type; + char *nvram; /* path to non-volatile RAM */ ++ char *templt; /* user override of path to master nvram */ + }; + + void virDomainLoaderDefFree(virDomainLoaderDefPtr loader); +diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug +index e7db7fe..62951da 100644 +--- a/src/qemu/libvirtd_qemu.aug ++++ b/src/qemu/libvirtd_qemu.aug +@@ -88,6 +88,8 @@ module Libvirtd_qemu = + + let log_entry = bool_entry "log_timestamp" + ++ let nvram_entry = str_array_entry "nvram" ++ + (* Each entry in the config is one of the following ... *) + let entry = vnc_entry + | spice_entry +@@ -100,6 +102,7 @@ module Libvirtd_qemu = + | rpc_entry + | network_entry + | log_entry ++ | nvram_entry + + let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ] + let empty = [ label "#empty" . eol ] +diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf +index 7bbbe09..79bba36 100644 +--- a/src/qemu/qemu.conf ++++ b/src/qemu/qemu.conf +@@ -487,3 +487,17 @@ + # Defaults to 1. + # + #log_timestamp = 0 ++ ++ ++# Location of master nvram file ++# ++# When a domain is configured to use UEFI instead of standard ++# BIOS it may use a separate storage for UEFI variables. If ++# that's the case libvirt creates the variable store per domain ++# using this master file as image. Each UEFI firmware can, ++# however, have different variables store. Therefore the nvram is ++# a list of strings when a single item is in form of: ++# ${PATH_TO_UEFI_FW}:${PATH_TO_UEFI_VARS}. ++# Later, when libvirt creates per domain variable store, this ++# list is searched for the master image. ++#nvram = [ "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" ] +diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c +index e2ec54f..ac10b64 100644 +--- a/src/qemu/qemu_conf.c ++++ b/src/qemu/qemu_conf.c +@@ -107,6 +107,9 @@ void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def) + VIR_FREE(def); + } + ++#define VIR_QEMU_LOADER_FILE_PATH "/usr/share/OVMF/OVMF_CODE.fd" ++#define VIR_QEMU_NVRAM_FILE_PATH "/usr/share/OVMF/OVMF_VARS.fd" ++ + virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) + { + virQEMUDriverConfigPtr cfg; +@@ -255,6 +258,15 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) + + cfg->logTimestamp = true; + ++ if (VIR_ALLOC_N(cfg->loader, 1) < 0 || ++ VIR_ALLOC_N(cfg->nvram, 1) < 0) ++ goto error; ++ cfg->nloader = 1; ++ ++ if (VIR_STRDUP(cfg->loader[0], VIR_QEMU_LOADER_FILE_PATH) < 0 || ++ VIR_STRDUP(cfg->nvram[0], VIR_QEMU_NVRAM_FILE_PATH) < 0) ++ goto error; ++ + return cfg; + + error: +@@ -305,6 +317,14 @@ static void virQEMUDriverConfigDispose(void *obj) + virStringFreeList(cfg->securityDriverNames); + + 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); + } + + +@@ -328,6 +348,43 @@ 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) + { +@@ -654,6 +711,43 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, + + GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); + ++ if ((p = virConfGetValue(conf, "nvram"))) { ++ size_t len; ++ virConfValuePtr pp; ++ ++ 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); ++ ++ /* Calc length and check items */ ++ for (len = 0, pp = p->list; pp; len++, pp = pp->next) { ++ if (pp->type != VIR_CONF_STRING) { ++ virReportError(VIR_ERR_CONF_SYNTAX, "%s", ++ _("nvram must be a list of strings")); ++ goto cleanup; ++ } ++ } ++ ++ if (len && ++ (VIR_ALLOC_N(cfg->loader, len) < 0 || ++ VIR_ALLOC_N(cfg->nvram, len) < 0)) ++ goto cleanup; ++ cfg->nloader = len; ++ ++ for (i = 0, pp = p->list; pp; i++, pp = pp->next) { ++ if (virQEMUDriverConfigNVRAMParse(pp->str, ++ &cfg->loader[i], ++ &cfg->nvram[i]) < 0) ++ goto cleanup; ++ } ++ } ++ + ret = 0; + + cleanup: +diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h +index ae7ac56..1f521e5 100644 +--- a/src/qemu/qemu_conf.h ++++ b/src/qemu/qemu_conf.h +@@ -172,6 +172,11 @@ struct _virQEMUDriverConfig { + int migrationPortMax; + + bool logTimestamp; ++ ++ /* Pairs of loader:nvram paths. The list is @nloader items long */ ++ char **loader; ++ char **nvram; ++ size_t nloader; + }; + + /* Main driver state */ +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index f68dfbe..5b120d4 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -67,6 +67,7 @@ + #include "virstring.h" + #include "virhostdev.h" + #include "storage/storage_driver.h" ++#include "configmake.h" + + #define VIR_FROM_THIS VIR_FROM_QEMU + +@@ -3734,6 +3735,135 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, + } + + ++static int ++qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, ++ virDomainDefPtr def, ++ bool migrated) ++{ ++ int ret = -1; ++ int srcFD = -1; ++ int dstFD = -1; ++ virDomainLoaderDefPtr loader = def->os.loader; ++ bool generated = false; ++ bool created = false; ++ ++ /* Unless domain has RO loader of pflash type, we have ++ * nothing to do here. If the loader is RW then it's not ++ * using split code and vars feature, so no nvram file needs ++ * to be created. */ ++ if (!loader || loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH || ++ loader->readonly != VIR_TRISTATE_SWITCH_ON) ++ return 0; ++ ++ /* If the nvram path is configured already, there's nothing ++ * we need to do. Unless we are starting the destination side ++ * of migration in which case nvram is configured in the ++ * domain XML but the file doesn't exist yet. Moreover, after ++ * the migration is completed, qemu will invoke a ++ * synchronization write into the nvram file so we don't have ++ * to take care about transmitting the real data on the other ++ * side. */ ++ if (loader->nvram && !migrated) ++ return 0; ++ ++ /* Autogenerate nvram path if needed.*/ ++ if (!loader->nvram) { ++ if (virAsprintf(&loader->nvram, ++ "%s/lib/libvirt/qemu/nvram/%s_VARS.fd", ++ LOCALSTATEDIR, def->name) < 0) ++ goto cleanup; ++ ++ generated = true; ++ } ++ ++ if (!virFileExists(loader->nvram)) { ++ const char *master_nvram_path = loader->templt; ++ ssize_t r; ++ ++ 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]; ++ break; ++ } ++ } ++ } ++ ++ if (!master_nvram_path) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("unable to find any master var store for " ++ "loader: %s"), loader->path); ++ goto cleanup; ++ } ++ ++ if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY, ++ 0, -1, -1, 0)) < 0) { ++ virReportSystemError(-srcFD, ++ _("Failed to open file '%s'"), ++ master_nvram_path); ++ goto cleanup; ++ } ++ if ((dstFD = virFileOpenAs(loader->nvram, ++ O_WRONLY | O_CREAT | O_EXCL, ++ S_IRUSR | S_IWUSR, ++ cfg->user, cfg->group, 0)) < 0) { ++ virReportSystemError(-dstFD, ++ _("Failed to create file '%s'"), ++ loader->nvram); ++ goto cleanup; ++ } ++ created = true; ++ ++ do { ++ char buf[1024]; ++ ++ if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) { ++ virReportSystemError(errno, ++ _("Unable to read from file '%s'"), ++ master_nvram_path); ++ goto cleanup; ++ } ++ ++ if (safewrite(dstFD, buf, r) < 0) { ++ virReportSystemError(errno, ++ _("Unable to write to file '%s'"), ++ loader->nvram); ++ goto cleanup; ++ } ++ } while (r); ++ ++ if (VIR_CLOSE(srcFD) < 0) { ++ virReportSystemError(errno, ++ _("Unable to close file '%s'"), ++ master_nvram_path); ++ goto cleanup; ++ } ++ if (VIR_CLOSE(dstFD) < 0) { ++ virReportSystemError(errno, ++ _("Unable to close file '%s'"), ++ loader->nvram); ++ goto cleanup; ++ } ++ } ++ ++ ret = 0; ++ cleanup: ++ /* We successfully generated the nvram path, but failed to ++ * copy the file content. Roll back. */ ++ if (ret < 0) { ++ if (created) ++ unlink(loader->nvram); ++ if (generated) ++ VIR_FREE(loader->nvram); ++ } ++ ++ VIR_FORCE_CLOSE(srcFD); ++ VIR_FORCE_CLOSE(dstFD); ++ return ret; ++} ++ ++ + int qemuProcessStart(virConnectPtr conn, + virQEMUDriverPtr driver, + virDomainObjPtr vm, +@@ -3802,6 +3932,13 @@ int qemuProcessStart(virConnectPtr conn, + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + goto cleanup; + ++ /* Some things, paths, ... are generated here and we want them to persist. ++ * Fill them in prior to setting the domain def as transient. */ ++ VIR_DEBUG("Generating paths"); ++ ++ if (qemuPrepareNVRAM(cfg, vm->def, migrateFrom) < 0) ++ goto cleanup; ++ + /* Do this upfront, so any part of the startup process can add + * runtime state to vm->def that won't be persisted. This let's us + * report implicit runtime defaults in the XML, like vnc listen/socket +diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in +index 7796acc..d2bc2c0 100644 +--- a/src/qemu/test_libvirtd_qemu.aug.in ++++ b/src/qemu/test_libvirtd_qemu.aug.in +@@ -74,3 +74,6 @@ module Test_libvirtd_qemu = + { "migration_port_min" = "49152" } + { "migration_port_max" = "49215" } + { "log_timestamp" = "0" } ++{ "nvram" ++ { "1" = "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" } ++} +diff --git a/tests/domainschemadata/domain-bios-nvram-empty.xml b/tests/domainschemadata/domain-bios-nvram-empty.xml +new file mode 100644 +index 0000000..e7643f3 +--- /dev/null ++++ b/tests/domainschemadata/domain-bios-nvram-empty.xml +@@ -0,0 +1,40 @@ ++ ++ test-bios ++ 362d1fc1-df7d-193e-5c18-49a71bd1da66 ++ 1048576 ++ 1048576 ++ 1 ++ ++ hvm ++ /usr/share/OVMF/OVMF_CODE.fd ++ ++ ++ ++ ++ ++ ++ ++ ++ destroy ++ restart ++ restart ++ ++ /usr/bin/qemu ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --git a/0014-nvram-Fix-permissions.patch b/0014-nvram-Fix-permissions.patch new file mode 100644 index 0000000..8f3d078 --- /dev/null +++ b/0014-nvram-Fix-permissions.patch @@ -0,0 +1,53 @@ +From 884ef00a28244b34d66ada97c8ddd3e7d7ea8ff1 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Thu, 11 Sep 2014 12:09:04 +0200 +Subject: [PATCH] nvram: Fix permissions + +I've noticed two problem with the automatically created NVRAM varstore +file. The first, even though I run qemu as root:root for some reason I +get Permission denied when trying to open the _VARS.fd file. The +problem is, the upper directory misses execute permissions, which in +combination with us dropping some capabilities result in EPERM. + +The next thing is, that if I switch SELinux to enforcing mode, I get +another EPERM because the vars file is not labeled correctly. It is +passed to qemu as disk and hence should be labelled as disk. QEMU may +write to it eventually, so this is different to kernel or initrd. + +Signed-off-by: Michal Privoznik +(cherry picked from commit 37d8c75fad297891b80086b125046ed3990eaf59) +--- + libvirt.spec.in | 2 +- + src/security/security_selinux.c | 5 ++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/libvirt.spec.in b/libvirt.spec.in +index 935b8c8..3cd7b2e 100644 +--- a/libvirt.spec.in ++++ b/libvirt.spec.in +@@ -1970,7 +1970,7 @@ exit 0 + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/ +-%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ ++%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ + %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/ + %{_datadir}/augeas/lenses/libvirtd_qemu.aug + %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug +diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c +index a409c19..b9efbc5 100644 +--- a/src/security/security_selinux.c ++++ b/src/security/security_selinux.c +@@ -2298,8 +2298,11 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr, + mgr) < 0) + return -1; + ++ /* This is different than kernel or initrd. The nvram store ++ * is really a disk, qemu can read and write to it. */ + if (def->os.loader && def->os.loader->nvram && +- virSecuritySELinuxSetFilecon(def->os.loader->nvram, data->content_context) < 0) ++ secdef && secdef->imagelabel && ++ virSecuritySELinuxSetFilecon(def->os.loader->nvram, secdef->imagelabel) < 0) + return -1; + + if (def->os.kernel && diff --git a/0015-virDomainUndefineFlags-Allow-NVRAM-unlinking.patch b/0015-virDomainUndefineFlags-Allow-NVRAM-unlinking.patch new file mode 100644 index 0000000..d9c9feb --- /dev/null +++ b/0015-virDomainUndefineFlags-Allow-NVRAM-unlinking.patch @@ -0,0 +1,148 @@ +From 03c156e5d54b311291101ca21690b586222be276 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Thu, 11 Sep 2014 13:17:11 +0200 +Subject: [PATCH] virDomainUndefineFlags: Allow NVRAM unlinking + +When a domain is undefined, there are options to remove it's +managed save state or snapshots. However, there's another file +that libvirt creates per domain: the NVRAM variable store file. +Make sure that the file is not left behind if the domain is +undefined. + +Signed-off-by: Michal Privoznik +(cherry picked from commit 273b6581ca8dae11e6ff40e3d13813fdbb37d41b) +--- + include/libvirt/libvirt.h.in | 2 ++ + src/qemu/qemu_driver.c | 20 +++++++++++++++++++- + tools/virsh-domain.c | 20 ++++++++++++++++---- + tools/virsh.pod | 6 +++++- + 4 files changed, 42 insertions(+), 6 deletions(-) + +diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in +index a64f597..8996231 100644 +--- a/include/libvirt/libvirt.h.in ++++ b/include/libvirt/libvirt.h.in +@@ -2257,6 +2257,8 @@ typedef enum { + VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = (1 << 1), /* If last use of domain, + then also remove any + snapshot metadata */ ++ VIR_DOMAIN_UNDEFINE_NVRAM = (1 << 2), /* Also remove any ++ nvram file */ + + /* Future undefine control flags should come here. */ + } virDomainUndefineFlagsValues; +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 239a300..588eba4 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -6402,7 +6402,8 @@ qemuDomainUndefineFlags(virDomainPtr dom, + virQEMUDriverConfigPtr cfg = NULL; + + virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE | +- VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA, -1); ++ VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA | ++ VIR_DOMAIN_UNDEFINE_NVRAM, -1); + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; +@@ -6451,6 +6452,23 @@ qemuDomainUndefineFlags(virDomainPtr dom, + } + } + ++ if (!virDomainObjIsActive(vm) && ++ vm->def->os.loader && vm->def->os.loader->nvram && ++ virFileExists(vm->def->os.loader->nvram)) { ++ if (!(flags & VIR_DOMAIN_UNDEFINE_NVRAM)) { ++ virReportError(VIR_ERR_OPERATION_INVALID, "%s", ++ _("cannot delete inactive domain with nvram")); ++ goto cleanup; ++ } ++ ++ if (unlink(vm->def->os.loader->nvram) < 0) { ++ virReportSystemError(errno, ++ _("failed to remove nvram: %s"), ++ vm->def->os.loader->nvram); ++ goto cleanup; ++ } ++ } ++ + if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0) + goto cleanup; + +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index c75cd73..d84db51 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -3038,6 +3038,10 @@ static const vshCmdOptDef opts_undefine[] = { + .type = VSH_OT_BOOL, + .help = N_("remove all domain snapshot metadata, if inactive") + }, ++ {.name = "nvram", ++ .type = VSH_OT_BOOL, ++ .help = N_("remove nvram file, if inactive") ++ }, + {.name = NULL} + }; + +@@ -3060,6 +3064,7 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) + bool snapshots_metadata = vshCommandOptBool(cmd, "snapshots-metadata"); + bool wipe_storage = vshCommandOptBool(cmd, "wipe-storage"); + bool remove_all_storage = vshCommandOptBool(cmd, "remove-all-storage"); ++ bool nvram = vshCommandOptBool(cmd, "nvram"); + /* Positive if these items exist. */ + int has_managed_save = 0; + int has_snapshots_metadata = 0; +@@ -3103,6 +3108,9 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) + flags |= VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA; + snapshots_safe = true; + } ++ if (nvram) { ++ flags |= VIR_DOMAIN_UNDEFINE_NVRAM; ++ } + + if (!(dom = vshCommandOptDomain(ctl, cmd, &name))) + return false; +@@ -3293,11 +3301,15 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd) + * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in 0.9.4, the + * VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA flag was not present + * until 0.9.5; skip to piecewise emulation if we couldn't prove +- * above that the new API is safe. */ +- if (managed_save_safe && snapshots_safe) { ++ * above that the new API is safe. ++ * Moreover, only the newer UndefineFlags() API understands ++ * the VIR_DOMAIN_UNDEFINE_NVRAM flag. So if user has ++ * specified --nvram we must use the Flags() API. */ ++ if ((managed_save_safe && snapshots_safe) || nvram) { + rc = virDomainUndefineFlags(dom, flags); +- if (rc == 0 || (last_error->code != VIR_ERR_NO_SUPPORT && +- last_error->code != VIR_ERR_INVALID_ARG)) ++ if (rc == 0 || nvram || ++ (last_error->code != VIR_ERR_NO_SUPPORT && ++ last_error->code != VIR_ERR_INVALID_ARG)) + goto out; + vshResetLibvirtError(); + } +diff --git a/tools/virsh.pod b/tools/virsh.pod +index ea9267e..a9fad73 100644 +--- a/tools/virsh.pod ++++ b/tools/virsh.pod +@@ -2058,7 +2058,7 @@ Output the device used for the TTY console of the domain. If the information + is not available the processes will provide an exit code of 1. + + =item B I [I<--managed-save>] [I<--snapshots-metadata>] +-[ {I<--storage> B | I<--remove-all-storage>} I<--wipe-storage>] ++[I<--nvram>] [ {I<--storage> B | I<--remove-all-storage>} I<--wipe-storage>] + + Undefine a domain. If the domain is running, this converts it to a + transient domain, without stopping it. If the domain is inactive, +@@ -2074,6 +2074,10 @@ domain. Without the flag, attempts to undefine an inactive domain with + snapshot metadata will fail. If the domain is active, this flag is + ignored. + ++The I<--nvram> flag ensures no nvram (/domain/os/nvram/) file is ++left behind. If the domain has an nvram file and the flag is ++omitted, the undefine will fail. ++ + The I<--storage> flag takes a parameter B, which is a comma separated + list of volume target names or source paths of storage volumes to be removed + along with the undefined domain. Volumes can be undefined and thus removed only diff --git a/0016-formatdomain-Update-loader-example-to-match-the-rest.patch b/0016-formatdomain-Update-loader-example-to-match-the-rest.patch new file mode 100644 index 0000000..6ed25e4 --- /dev/null +++ b/0016-formatdomain-Update-loader-example-to-match-the-rest.patch @@ -0,0 +1,32 @@ +From 2b30f114b796aee6f92eb13244f8cd42ef523bfe Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Fri, 12 Sep 2014 13:18:32 +0200 +Subject: [PATCH] formatdomain: Update example to match the rest + +At the beginning when I was inventing attributes and + I've introduced this @readonly attribute to the loader +element. It accepted values 'on' and 'off'. However, later, during the +review process, that has changed to 'yes' and 'no', but the example +XML snippet wasn't updated, so while the description is correct, the +example isn't. + +Reported-by: Laszlo Ersek +Signed-off-by: Michal Privoznik +(cherry picked from commit dcf7d0423c1ad79e45df4ddd1cb619603cf221e7) +--- + docs/formatdomain.html.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in +index a2ea758..5081be3 100644 +--- a/docs/formatdomain.html.in ++++ b/docs/formatdomain.html.in +@@ -102,7 +102,7 @@ + ... + <os> + <type>hvm</type> +- <loader readonly='on' type='rom'>/usr/lib/xen/boot/hvmloader</loader> ++ <loader readonly='yes' type='rom'>/usr/lib/xen/boot/hvmloader</loader> + <nvram template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/nvram/guest_VARS.fd</nvram> + <boot dev='hd'/> + <boot dev='cdrom'/> diff --git a/0017-domaincaps-Expose-UEFI-capability.patch b/0017-domaincaps-Expose-UEFI-capability.patch new file mode 100644 index 0000000..98de34a --- /dev/null +++ b/0017-domaincaps-Expose-UEFI-capability.patch @@ -0,0 +1,338 @@ +From 2c4e9da2b46d55fda49b20ae48dbdd4e63209565 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Tue, 16 Sep 2014 14:47:47 +0200 +Subject: [PATCH] domaincaps: Expose UEFI capability + +As of 542899168c38 we learned libvirt to use UEFI for domains. +However, management applications may firstly query if libvirt +supports it. And this is where virConnectGetDomainCapabilities() +API comes handy. + +Signed-off-by: Michal Privoznik +(cherry picked from commit 4f76621c0edb895431a6fc30c026865dbf1c1316) +--- + docs/formatdomaincaps.html.in | 40 ++++++++++++++++++++++ + docs/schemas/domaincaps.rng | 21 ++++++++++++ + src/conf/domain_capabilities.c | 28 +++++++++++++++ + src/conf/domain_capabilities.h | 16 +++++++++ + src/qemu/qemu_capabilities.c | 38 ++++++++++++++++++++ + tests/domaincapsschemadata/domaincaps-basic.xml | 1 + + tests/domaincapsschemadata/domaincaps-full.xml | 13 +++++++ + .../domaincaps-qemu_1.6.50-1.xml | 12 +++++++ + tests/domaincapstest.c | 8 +++++ + 9 files changed, 177 insertions(+) + +diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in +index 66b6017..34d746d 100644 +--- a/docs/formatdomaincaps.html.in ++++ b/docs/formatdomaincaps.html.in +@@ -93,6 +93,46 @@ +
The maximum number of supported virtual CPUs
+ + ++

BIOS bootloader

++ ++

Sometimes users might want to tweak some BIOS knobs or use ++ UEFI. For cases like that, os ++ element exposes what values can be passed to its children.

++ ++
++<domainCapabilities>
++  ...
++  <os supported='yes'>
++    <loader supported='yes'>
++      <enum name='type'>
++        <value>rom</value>
++        <value>pflash</value>
++      </enum>
++      <enum name='readonly'>
++        <value>yes</value>
++        <value>no</value>
++      </enum>
++    </loader>
++  </os>
++  ...
++<domainCapabilities>
++
++ ++

For the loader element, the following can occur:

++ ++
++
type
++
Whether loader is a typical BIOS (rom) or ++ an UEFI binary (pflash). This refers to ++ type attribute of the <loader/> ++ element.
++ ++
readonly
++
Options for the readonly attribute of the ++ <loader/> element.
++
++ +

Devices

+ +

+diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng +index 627b699..ad8d966 100644 +--- a/docs/schemas/domaincaps.rng ++++ b/docs/schemas/domaincaps.rng +@@ -26,6 +26,9 @@ + + + ++ ++ ++ + + + +@@ -41,6 +44,24 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c +index df190eb..5a3c8e7 100644 +--- a/src/conf/domain_capabilities.c ++++ b/src/conf/domain_capabilities.c +@@ -178,6 +178,32 @@ virDomainCapsEnumFormat(virBufferPtr buf, + #capsEnum, valToStr); \ + } while (0) + ++ ++static void ++virDomainCapsLoaderFormat(virBufferPtr buf, ++ virDomainCapsLoaderPtr loader) ++{ ++ FORMAT_PROLOGUE(loader); ++ ++ ENUM_PROCESS(loader, type, virDomainLoaderTypeToString); ++ ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString); ++ ++ FORMAT_EPILOGUE(loader); ++} ++ ++static void ++virDomainCapsOSFormat(virBufferPtr buf, ++ virDomainCapsOSPtr os) ++{ ++ virDomainCapsLoaderPtr loader = &os->loader; ++ ++ FORMAT_PROLOGUE(os); ++ ++ virDomainCapsLoaderFormat(buf, loader); ++ ++ FORMAT_EPILOGUE(os); ++} ++ + static void + virDomainCapsDeviceDiskFormat(virBufferPtr buf, + virDomainCapsDeviceDiskPtr const disk) +@@ -225,6 +251,8 @@ virDomainCapsFormatInternal(virBufferPtr buf, + if (caps->maxvcpus) + virBufferAsprintf(buf, "\n", caps->maxvcpus); + ++ virDomainCapsOSFormat(buf, &caps->os); ++ + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + +diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h +index 731e66f..768646b 100644 +--- a/src/conf/domain_capabilities.h ++++ b/src/conf/domain_capabilities.h +@@ -43,6 +43,21 @@ struct _virDomainCapsDevice { + bool supported; /* true if is supported by hypervisor */ + }; + ++typedef struct _virDomainCapsLoader virDomainCapsLoader; ++typedef virDomainCapsLoader *virDomainCapsLoaderPtr; ++struct _virDomainCapsLoader { ++ virDomainCapsDevice device; ++ virDomainCapsEnum type; /* Info about virDomainLoader */ ++ virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */ ++}; ++ ++typedef struct _virDomainCapsOS virDomainCapsOS; ++typedef virDomainCapsOS *virDomainCapsOSPtr; ++struct _virDomainCapsOS { ++ virDomainCapsDevice device; ++ virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ ++}; ++ + typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk; + typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; + struct _virDomainCapsDeviceDisk { +@@ -75,6 +90,7 @@ struct _virDomainCaps { + /* Some machine specific info */ + int maxvcpus; + ++ virDomainCapsOS os; + virDomainCapsDeviceDisk disk; + virDomainCapsDeviceHostdev hostdev; + /* add new domain devices here */ +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index c70a1a8..c999ee4 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -3609,6 +3609,42 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps) + + + static void ++virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, ++ virDomainCapsLoaderPtr loader, ++ virArch arch) ++{ ++ loader->device.supported = true; ++ ++ VIR_DOMAIN_CAPS_ENUM_SET(loader->type, ++ VIR_DOMAIN_LOADER_TYPE_ROM); ++ ++ if (arch == VIR_ARCH_X86_64 && ++ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE) && ++ virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) ++ VIR_DOMAIN_CAPS_ENUM_SET(loader->type, ++ VIR_DOMAIN_LOADER_TYPE_PFLASH); ++ ++ ++ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) ++ VIR_DOMAIN_CAPS_ENUM_SET(loader->readonly, ++ VIR_TRISTATE_BOOL_YES, ++ VIR_TRISTATE_BOOL_NO); ++} ++ ++ ++static void ++virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, ++ virDomainCapsOSPtr os, ++ virArch arch) ++{ ++ virDomainCapsLoaderPtr loader = &os->loader; ++ ++ os->device.supported = true; ++ virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch); ++} ++ ++ ++static void + virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsDeviceDiskPtr disk) + { +@@ -3686,12 +3722,14 @@ void + virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, + virQEMUCapsPtr qemuCaps) + { ++ virDomainCapsOSPtr os = &domCaps->os; + virDomainCapsDeviceDiskPtr disk = &domCaps->disk; + virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; + int maxvcpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, domCaps->machine); + + domCaps->maxvcpus = maxvcpus; + ++ virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch); + virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk); + virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev); + } +diff --git a/tests/domaincapsschemadata/domaincaps-basic.xml b/tests/domaincapsschemadata/domaincaps-basic.xml +index 9963519..6171393 100644 +--- a/tests/domaincapsschemadata/domaincaps-basic.xml ++++ b/tests/domaincapsschemadata/domaincaps-basic.xml +@@ -3,6 +3,7 @@ + uml + my-machine-type + x86_64 ++ + + + +diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml +index 58dd4cb..9722772 100644 +--- a/tests/domaincapsschemadata/domaincaps-full.xml ++++ b/tests/domaincapsschemadata/domaincaps-full.xml +@@ -4,6 +4,19 @@ + my-machine-type + x86_64 + ++ ++ ++ ++ rom ++ pflash ++ ++ ++ default ++ yes ++ no ++ ++ ++ + + + +diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +index 8b63993..568cecb 100644 +--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml ++++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +@@ -3,6 +3,18 @@ + kvm + pc-1.2 + x86_64 ++ ++ ++ ++ rom ++ pflash ++ ++ ++ yes ++ no ++ ++ ++ + + + +diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c +index 78197e2..f240643 100644 +--- a/tests/domaincapstest.c ++++ b/tests/domaincapstest.c +@@ -38,10 +38,18 @@ static void + fillAll(virDomainCapsPtr domCaps, + void *opaque ATTRIBUTE_UNUSED) + { ++ virDomainCapsOSPtr os = &domCaps->os; ++ virDomainCapsLoaderPtr loader = &os->loader; + virDomainCapsDeviceDiskPtr disk = &domCaps->disk; + virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; + domCaps->maxvcpus = 255; + ++ os->device.supported = true; ++ ++ loader->device.supported = true; ++ SET_ALL_BITS(loader->type); ++ SET_ALL_BITS(loader->readonly); ++ + disk->device.supported = true; + SET_ALL_BITS(disk->diskDevice); + SET_ALL_BITS(disk->bus); diff --git a/0018-qemu_capabilities-Change-virQEMUCapsFillDomainCaps-s.patch b/0018-qemu_capabilities-Change-virQEMUCapsFillDomainCaps-s.patch new file mode 100644 index 0000000..23ec2a5 --- /dev/null +++ b/0018-qemu_capabilities-Change-virQEMUCapsFillDomainCaps-s.patch @@ -0,0 +1,192 @@ +From 103a146b669a778238485425f4eb69a5a1f5c747 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Wed, 17 Sep 2014 11:33:35 +0200 +Subject: [PATCH] qemu_capabilities: Change virQEMUCapsFillDomainCaps signature + +Up till now the virQEMUCapsFillDomainCaps() was type of void as +there was no way for it to fail. This is, however, going to +change in the next commit. + +Signed-off-by: Michal Privoznik +(cherry picked from commit 2b2e4a7acff5574dd82bfbd61a638270f6be54ef) +--- + src/qemu/qemu_capabilities.c | 25 ++++++++++++++++--------- + src/qemu/qemu_capabilities.h | 4 ++-- + src/qemu/qemu_driver.c | 3 ++- + tests/domaincapstest.c | 19 ++++++++++++------- + 4 files changed, 32 insertions(+), 19 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index c999ee4..d2e5f47 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -3608,7 +3608,7 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps) + } + + +-static void ++static int + virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsLoaderPtr loader, + virArch arch) +@@ -3629,10 +3629,11 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, + VIR_DOMAIN_CAPS_ENUM_SET(loader->readonly, + VIR_TRISTATE_BOOL_YES, + VIR_TRISTATE_BOOL_NO); ++ return 0; + } + + +-static void ++static int + virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsOSPtr os, + virArch arch) +@@ -3640,11 +3641,13 @@ virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsLoaderPtr loader = &os->loader; + + os->device.supported = true; +- virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch); ++ if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0) ++ return -1; ++ return 0; + } + + +-static void ++static int + virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsDeviceDiskPtr disk) + { +@@ -3667,10 +3670,11 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) + VIR_DOMAIN_CAPS_ENUM_SET(disk->bus, VIR_DOMAIN_DISK_BUS_USB); ++ return 0; + } + + +-static void ++static int + virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsDeviceHostdevPtr hostdev) + { +@@ -3715,10 +3719,11 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM); + } ++ return 0; + } + + +-void ++int + virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, + virQEMUCapsPtr qemuCaps) + { +@@ -3729,7 +3734,9 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, + + domCaps->maxvcpus = maxvcpus; + +- virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch); +- virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk); +- virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev); ++ if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 || ++ virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 || ++ virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0) ++ return -1; ++ return 0; + } +diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h +index 0980c00..828bba3 100644 +--- a/src/qemu/qemu_capabilities.h ++++ b/src/qemu/qemu_capabilities.h +@@ -324,7 +324,7 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps, + virQEMUCapsPtr kvmbinCaps, + virArch guestarch); + +-void virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, +- virQEMUCapsPtr qemuCaps); ++int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, ++ virQEMUCapsPtr qemuCaps); + + #endif /* __QEMU_CAPABILITIES_H__*/ +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 588eba4..9c1644c 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -17205,7 +17205,8 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn, + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype))) + goto cleanup; + +- virQEMUCapsFillDomainCaps(domCaps, qemuCaps); ++ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0) ++ goto cleanup; + + ret = virDomainCapsFormat(domCaps); + cleanup: +diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c +index f240643..0c4b09f 100644 +--- a/tests/domaincapstest.c ++++ b/tests/domaincapstest.c +@@ -28,13 +28,13 @@ + + #define VIR_FROM_THIS VIR_FROM_NONE + +-typedef void (*virDomainCapsFill)(virDomainCapsPtr domCaps, +- void *opaque); ++typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps, ++ void *opaque); + + #define SET_ALL_BITS(x) \ + memset(&(x.values), 0xff, sizeof(x.values)) + +-static void ++static int + fillAll(virDomainCapsPtr domCaps, + void *opaque ATTRIBUTE_UNUSED) + { +@@ -60,18 +60,20 @@ fillAll(virDomainCapsPtr domCaps, + SET_ALL_BITS(hostdev->subsysType); + SET_ALL_BITS(hostdev->capsType); + SET_ALL_BITS(hostdev->pciBackend); ++ return 0; + } + + + #ifdef WITH_QEMU + # include "testutilsqemu.h" +-static void ++static int + fillQemuCaps(virDomainCapsPtr domCaps, + void *opaque) + { + virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque; + +- virQEMUCapsFillDomainCaps(domCaps, qemuCaps); ++ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0) ++ return -1; + + /* The function above tries to query host's KVM & VFIO capabilities by + * calling qemuHostdevHostSupportsPassthroughLegacy() and +@@ -82,6 +84,7 @@ fillQemuCaps(virDomainCapsPtr domCaps, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); ++ return 0; + } + #endif /* WITH_QEMU */ + +@@ -99,8 +102,10 @@ buildVirDomainCaps(const char *emulatorbin, + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type))) + goto cleanup; + +- if (fillFunc) +- fillFunc(domCaps, opaque); ++ if (fillFunc && fillFunc(domCaps, opaque) < 0) { ++ virObjectUnref(domCaps); ++ domCaps = NULL; ++ } + + cleanup: + return domCaps; diff --git a/0019-domaincaps-Expose-UEFI-binary-path-if-it-exists.patch b/0019-domaincaps-Expose-UEFI-binary-path-if-it-exists.patch new file mode 100644 index 0000000..fb27137 --- /dev/null +++ b/0019-domaincaps-Expose-UEFI-binary-path-if-it-exists.patch @@ -0,0 +1,444 @@ +From 64041dc7d34d7af3fd611d194bf2ab56729a13fa Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Tue, 16 Sep 2014 19:52:54 -0400 +Subject: [PATCH] domaincaps: Expose UEFI binary path, if it exists + +Check to see if the UEFI binary mentioned in qemu.conf actually +exists, and if so expose it in domcapabilities like + + + /path/to/ovmf + + +We introduce some generic domcaps infrastructure for handling +a dynamic list of string values, it may be of use for future bits. + +Signed-off-by: Michal Privoznik +(cherry picked from commit f05b6a918e283929f5d837cd1668cdcdb3834b9a) +--- + docs/formatdomaincaps.html.in | 6 +++ + docs/schemas/domaincaps.rng | 17 +++++--- + src/conf/domain_capabilities.c | 29 +++++++++++++ + src/conf/domain_capabilities.h | 8 ++++ + src/qemu/qemu_capabilities.c | 32 +++++++++++--- + src/qemu/qemu_capabilities.h | 7 +++- + src/qemu/qemu_driver.c | 6 ++- + tests/domaincapsschemadata/domaincaps-full.xml | 2 + + .../domaincaps-qemu_1.6.50-1.xml | 1 + + tests/domaincapstest.c | 49 +++++++++++++++++++--- + 10 files changed, 140 insertions(+), 17 deletions(-) + +diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in +index 34d746d..6959dfe 100644 +--- a/docs/formatdomaincaps.html.in ++++ b/docs/formatdomaincaps.html.in +@@ -105,6 +105,7 @@ + ... + <os supported='yes'> + <loader supported='yes'> ++ <value>/usr/share/OVMF/OVMF_CODE.fd</value> + <enum name='type'> + <value>rom</value> + <value>pflash</value> +@@ -122,6 +123,11 @@ +

For the loader element, the following can occur:

+ +
++
value
++
List of known loader paths. Currently this is only used ++ to advertise known locations of OVMF binaries for qemu. Binaries ++ will only be listed if they actually exist on disk.
++ +
type
+
Whether loader is a typical BIOS (rom) or + an UEFI binary (pflash). This refers to +diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng +index ad8d966..f4a555f 100644 +--- a/docs/schemas/domaincaps.rng ++++ b/docs/schemas/domaincaps.rng +@@ -47,6 +47,9 @@ + + + ++ ++ ++ + + + +@@ -85,6 +88,14 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ + + + +@@ -100,11 +111,7 @@ + + + +- +- +- +- +- ++ + + + +diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c +index 5a3c8e7..7c59912 100644 +--- a/src/conf/domain_capabilities.c ++++ b/src/conf/domain_capabilities.c +@@ -48,12 +48,28 @@ VIR_ONCE_GLOBAL_INIT(virDomainCaps) + + + static void ++virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values) ++{ ++ size_t i; ++ ++ if (!values || !values->values) ++ return; ++ ++ for (i = 0; i < values->nvalues; i++) ++ VIR_FREE(values->values[i]); ++ VIR_FREE(values->values); ++} ++ ++ ++static void + virDomainCapsDispose(void *obj) + { + virDomainCapsPtr caps = obj; + + VIR_FREE(caps->path); + VIR_FREE(caps->machine); ++ ++ virDomainCapsStringValuesFree(&caps->os.loader.values); + } + + +@@ -156,6 +172,18 @@ virDomainCapsEnumFormat(virBufferPtr buf, + return ret; + } + ++ ++static void ++virDomainCapsStringValuesFormat(virBufferPtr buf, ++ virDomainCapsStringValuesPtr values) ++{ ++ size_t i; ++ ++ for (i = 0; i < values->nvalues; i++) ++ virBufferEscapeString(buf, "%s\n", values->values[i]); ++} ++ ++ + #define FORMAT_PROLOGUE(item) \ + do { \ + virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \ +@@ -185,6 +213,7 @@ virDomainCapsLoaderFormat(virBufferPtr buf, + { + FORMAT_PROLOGUE(loader); + ++ virDomainCapsStringValuesFormat(buf, &loader->values); + ENUM_PROCESS(loader, type, virDomainLoaderTypeToString); + ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString); + +diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h +index 768646b..597ac75 100644 +--- a/src/conf/domain_capabilities.h ++++ b/src/conf/domain_capabilities.h +@@ -37,6 +37,13 @@ struct _virDomainCapsEnum { + unsigned int values; /* Bitmask of values supported in the corresponding enum */ + }; + ++typedef struct _virDomainCapsStringValues virDomainCapsStringValues; ++typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr; ++struct _virDomainCapsStringValues { ++ char **values; /* raw string values */ ++ size_t nvalues; /* number of strings */ ++}; ++ + typedef struct _virDomainCapsDevice virDomainCapsDevice; + typedef virDomainCapsDevice *virDomainCapsDevicePtr; + struct _virDomainCapsDevice { +@@ -47,6 +54,7 @@ typedef struct _virDomainCapsLoader virDomainCapsLoader; + typedef virDomainCapsLoader *virDomainCapsLoaderPtr; + struct _virDomainCapsLoader { + virDomainCapsDevice device; ++ virDomainCapsStringValues values; /* Info about values for the element */ + virDomainCapsEnum type; /* Info about virDomainLoader */ + virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */ + }; +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index d2e5f47..651bacd 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -3611,10 +3611,30 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps) + static int + virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsLoaderPtr loader, +- virArch arch) ++ virArch arch, ++ virQEMUDriverConfigPtr cfg) + { ++ size_t i; ++ + loader->device.supported = true; + ++ if (VIR_ALLOC_N(loader->values.values, cfg->nloader) < 0) ++ return -1; ++ ++ for (i = 0; i < cfg->nloader; i++) { ++ const char *filename = cfg->loader[i]; ++ ++ if (!virFileExists(filename)) { ++ VIR_DEBUG("loader filename=%s does not exist", filename); ++ continue; ++ } ++ ++ if (VIR_STRDUP(loader->values.values[loader->values.nvalues], ++ filename) < 0) ++ return -1; ++ loader->values.nvalues++; ++ } ++ + VIR_DOMAIN_CAPS_ENUM_SET(loader->type, + VIR_DOMAIN_LOADER_TYPE_ROM); + +@@ -3636,12 +3656,13 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, + static int + virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsOSPtr os, +- virArch arch) ++ virArch arch, ++ virQEMUDriverConfigPtr cfg) + { + virDomainCapsLoaderPtr loader = &os->loader; + + os->device.supported = true; +- if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0) ++ if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch, cfg) < 0) + return -1; + return 0; + } +@@ -3725,7 +3746,8 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, + + int + virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, +- virQEMUCapsPtr qemuCaps) ++ virQEMUCapsPtr qemuCaps, ++ virQEMUDriverConfigPtr cfg) + { + virDomainCapsOSPtr os = &domCaps->os; + virDomainCapsDeviceDiskPtr disk = &domCaps->disk; +@@ -3734,7 +3756,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, + + domCaps->maxvcpus = maxvcpus; + +- if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 || ++ if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch, cfg) < 0 || + virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 || + virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0) + return -1; +diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h +index 828bba3..cf69e59 100644 +--- a/src/qemu/qemu_capabilities.h ++++ b/src/qemu/qemu_capabilities.h +@@ -324,7 +324,12 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps, + virQEMUCapsPtr kvmbinCaps, + virArch guestarch); + ++/* Forward declaration */ ++typedef struct _virQEMUDriverConfig virQEMUDriverConfig; ++typedef virQEMUDriverConfig *virQEMUDriverConfigPtr; ++ + int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, +- virQEMUCapsPtr qemuCaps); ++ virQEMUCapsPtr qemuCaps, ++ virQEMUDriverConfigPtr cfg); + + #endif /* __QEMU_CAPABILITIES_H__*/ +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 9c1644c..0d895c6 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -17133,12 +17133,15 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn, + int virttype; /* virDomainVirtType */ + virDomainCapsPtr domCaps = NULL; + int arch = virArchFromHost(); /* virArch */ ++ virQEMUDriverConfigPtr cfg = NULL; + + virCheckFlags(0, ret); + + if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0) + return ret; + ++ cfg = virQEMUDriverGetConfig(driver); ++ + if (qemuHostdevHostSupportsPassthroughLegacy()) + virttype = VIR_DOMAIN_VIRT_KVM; + else +@@ -17205,11 +17208,12 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn, + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype))) + goto cleanup; + +- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0) ++ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0) + goto cleanup; + + ret = virDomainCapsFormat(domCaps); + cleanup: ++ virObjectUnref(cfg); + virObjectUnref(domCaps); + virObjectUnref(qemuCaps); + return ret; +diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml +index 9722772..96202bc 100644 +--- a/tests/domaincapsschemadata/domaincaps-full.xml ++++ b/tests/domaincapsschemadata/domaincaps-full.xml +@@ -6,6 +6,8 @@ + + + ++ /foo/bar ++ /tmp/my_path + + rom + pflash +diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +index 568cecb..346ef65 100644 +--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml ++++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +@@ -5,6 +5,7 @@ + x86_64 + + ++ /usr/share/OVMF/OVMF_CODE.fd + + rom + pflash +diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c +index 0c4b09f..8543963 100644 +--- a/tests/domaincapstest.c ++++ b/tests/domaincapstest.c +@@ -34,6 +34,27 @@ typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps, + #define SET_ALL_BITS(x) \ + memset(&(x.values), 0xff, sizeof(x.values)) + ++static int ATTRIBUTE_SENTINEL ++fillStringValues(virDomainCapsStringValuesPtr values, ...) ++{ ++ int ret = 0; ++ va_list list; ++ const char *str; ++ ++ va_start(list, values); ++ while ((str = va_arg(list, const char *))) { ++ if (VIR_REALLOC_N(values->values, values->nvalues + 1) < 0 || ++ VIR_STRDUP(values->values[values->nvalues], str) < 0) { ++ ret = -1; ++ break; ++ } ++ values->nvalues++; ++ } ++ va_end(list); ++ ++ return ret; ++} ++ + static int + fillAll(virDomainCapsPtr domCaps, + void *opaque ATTRIBUTE_UNUSED) +@@ -49,6 +70,11 @@ fillAll(virDomainCapsPtr domCaps, + loader->device.supported = true; + SET_ALL_BITS(loader->type); + SET_ALL_BITS(loader->readonly); ++ if (fillStringValues(&loader->values, ++ "/foo/bar", ++ "/tmp/my_path", ++ NULL) < 0) ++ return -1; + + disk->device.supported = true; + SET_ALL_BITS(disk->diskDevice); +@@ -66,13 +92,21 @@ fillAll(virDomainCapsPtr domCaps, + + #ifdef WITH_QEMU + # include "testutilsqemu.h" ++ ++struct fillQemuCapsData { ++ virQEMUCapsPtr qemuCaps; ++ virQEMUDriverConfigPtr cfg; ++}; ++ + static int + fillQemuCaps(virDomainCapsPtr domCaps, + void *opaque) + { +- virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque; ++ struct fillQemuCapsData *data = (struct fillQemuCapsData *) opaque; ++ virQEMUCapsPtr qemuCaps = data->qemuCaps; ++ virQEMUDriverConfigPtr cfg = data->cfg; + +- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0) ++ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0) + return -1; + + /* The function above tries to query host's KVM & VFIO capabilities by +@@ -97,7 +131,7 @@ buildVirDomainCaps(const char *emulatorbin, + virDomainCapsFill fillFunc, + void *opaque) + { +- virDomainCapsPtr domCaps; ++ virDomainCapsPtr domCaps, ret = NULL; + + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type))) + goto cleanup; +@@ -107,8 +141,9 @@ buildVirDomainCaps(const char *emulatorbin, + domCaps = NULL; + } + ++ ret = domCaps; + cleanup: +- return domCaps; ++ return ret; + } + + struct test_virDomainCapsFormatData { +@@ -182,13 +217,16 @@ mymain(void) + + #ifdef WITH_QEMU + ++ virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false); ++ + # define DO_TEST_QEMU(Filename, QemuCapsFile, Emulatorbin, Machine, Arch, Type, ...) \ + do { \ + const char *capsPath = abs_srcdir "/qemucapabilitiesdata/" QemuCapsFile ".caps"; \ + virQEMUCapsPtr qemuCaps = qemuTestParseCapabilities(capsPath); \ ++ struct fillQemuCapsData fillData = {.qemuCaps = qemuCaps, .cfg = cfg}; \ + struct test_virDomainCapsFormatData data = {.filename = Filename, \ + .emulatorbin = Emulatorbin, .machine = Machine, .arch = Arch, \ +- .type = Type, .fillFunc = fillQemuCaps, .opaque = qemuCaps}; \ ++ .type = Type, .fillFunc = fillQemuCaps, .opaque = &fillData}; \ + if (!qemuCaps) { \ + fprintf(stderr, "Unable to build qemu caps from %s\n", capsPath); \ + ret = -1; \ +@@ -199,6 +237,7 @@ mymain(void) + DO_TEST_QEMU("qemu_1.6.50-1", "caps_1.6.50-1", "/usr/bin/qemu-system-x86_64", + "pc-1.2", VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_KVM); + ++ virObjectUnref(cfg); + #endif /* WITH_QEMU */ + + return ret; diff --git a/0020-domaincapstest-Run-cleanly-on-systems-missing-OVMF-f.patch b/0020-domaincapstest-Run-cleanly-on-systems-missing-OVMF-f.patch new file mode 100644 index 0000000..9b1d453 --- /dev/null +++ b/0020-domaincapstest-Run-cleanly-on-systems-missing-OVMF-f.patch @@ -0,0 +1,40 @@ +From 6fcd1ae861279589172783c4937367685469f265 Mon Sep 17 00:00:00 2001 +From: Michal Privoznik +Date: Wed, 17 Sep 2014 17:17:03 +0200 +Subject: [PATCH] domaincapstest: Run cleanly on systems missing OVMF firmware + +As of f05b6a918e28 the test produces the list of paths that can +be passed to and libvirt knows about them. However, +during the process of generating the list the paths are checked +for their presence. This may produce different results on +different systems. Therefore, the path - if missing - is +added to pretend it's there. + +Signed-off-by: Michal Privoznik +(cherry picked from commit b3f42da6b77644107bcbaf720d7ed9cef5c798a2) +--- + tests/domaincapstest.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c +index 8543963..067ad4d 100644 +--- a/tests/domaincapstest.c ++++ b/tests/domaincapstest.c +@@ -118,6 +118,17 @@ fillQemuCaps(virDomainCapsPtr domCaps, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO); ++ ++ /* Moreover, as of f05b6a918e28 we are expecting to see ++ * OVMF_CODE.fd file which may not exists everywhere. */ ++ if (!domCaps->os.loader.values.nvalues) { ++ virDomainCapsLoaderPtr loader = &domCaps->os.loader; ++ ++ if (fillStringValues(&loader->values, ++ "/usr/share/OVMF/OVMF_CODE.fd", ++ NULL) < 0) ++ return -1; ++ } + return 0; + } + #endif /* WITH_QEMU */ diff --git a/libvirt.spec b/libvirt.spec index 6044558..ada2e30 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -366,7 +366,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 1.2.8 -Release: 3%{?dist}%{?extra_release} +Release: 4%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -382,7 +382,6 @@ Source: http://libvirt.org/sources/%{?mainturl}libvirt-%{version}.tar.gz Patch0001: 0001-network-try-to-eliminate-default-network-conflict-du.patch Patch0002: 0002-network-detect-conflicting-route-even-if-it-is-the-f.patch # Fix directory creation at session daemon startup (bz #1139672) -# (Patch 5 is posted but not in git as of 2014-09-15) Patch0003: 0003-rpc-reformat-the-flow-to-make-a-bit-more-sense.patch Patch0004: 0004-remove-redundant-pidfile-path-constructions.patch Patch0005: 0005-util-fix-potential-leak-in-error-codepath.patch @@ -393,6 +392,19 @@ Patch0007: 0007-rpc-make-daemon-spawning-a-bit-more-intelligent.patch Patch0008: 0008-spec-Don-t-build-wireshark-on-f21-non-upstream.patch # Fix preun script (bz #1142367) Patch0009: 0009-spec-Fix-preun-script-for-daemon.patch +# Don't mess up labelling of /dev/net/tun (bz #1141879) +Patch0010: 0010-virSecuritySELinuxSetTapFDLabel-Temporarily-revert-t.patch +# pflash/nvram support for UEFI/OVMF +Patch0011: 0011-conf-Extend-loader-and-introduce-nvram.patch +Patch0012: 0012-qemu-Implement-extended-loader-and-nvram.patch +Patch0013: 0013-qemu-Automatically-create-NVRAM-store.patch +Patch0014: 0014-nvram-Fix-permissions.patch +Patch0015: 0015-virDomainUndefineFlags-Allow-NVRAM-unlinking.patch +Patch0016: 0016-formatdomain-Update-loader-example-to-match-the-rest.patch +Patch0017: 0017-domaincaps-Expose-UEFI-capability.patch +Patch0018: 0018-qemu_capabilities-Change-virQEMUCapsFillDomainCaps-s.patch +Patch0019: 0019-domaincaps-Expose-UEFI-binary-path-if-it-exists.patch +Patch0020: 0020-domaincapstest-Run-cleanly-on-systems-missing-OVMF-f.patch %if %{with_libvirtd} Requires: libvirt-daemon = %{version}-%{release} @@ -1223,7 +1235,6 @@ driver %patch0001 -p1 %patch0002 -p1 # Fix directory creation at session daemon startup (bz #1139672) -# (Patch 5 is posted but not in git as of 2014-09-15) %patch0003 -p1 %patch0004 -p1 %patch0005 -p1 @@ -1234,6 +1245,19 @@ driver %patch0008 -p1 # Fix preun script (bz #1142367) %patch0009 -p1 +# Don't mess up labelling of /dev/net/tun (bz #1141879) +%patch0010 -p1 +# pflash/nvram support for UEFI/OVMF +%patch0011 -p1 +%patch0012 -p1 +%patch0013 -p1 +%patch0014 -p1 +%patch0015 -p1 +%patch0016 -p1 +%patch0017 -p1 +%patch0018 -p1 +%patch0019 -p1 +%patch0020 -p1 %build %if ! %{with_xen} @@ -2004,6 +2028,7 @@ exit 0 %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/ +%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/ %{_datadir}/augeas/lenses/libvirtd_qemu.aug %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug @@ -2106,6 +2131,7 @@ exit 0 %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/ +%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/ %dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/ %{_datadir}/augeas/lenses/libvirtd_qemu.aug %{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug @@ -2309,6 +2335,10 @@ exit 0 %doc examples/systemtap %changelog +* Thu Sep 18 2014 Cole Robinson - 1.2.8-4 +- Don't mess up labelling of /dev/net/tun (bz #1141879) +- pflash/nvram support for UEFI/OVMF + * Wed Sep 17 2014 Cole Robinson - 1.2.8-3 - Fix preun script (bz #1142367)