[libvirt] [PATCH v1 0/3] OVMF exposure

Not so long ago, QEMU introduced support for UEFI instead of standard BIOS. Our domain XML needs to be adjusted, however. Users are expected to use mainly OVMF which works in two modes: 1) UEFI code and UEFI variables are mixed in one file 2) The code and variables are split in two separate files For the case number one we are almost ready. The second case, however, needs more changes on our side. Especially if you consider fact, that the UEFI code can be shared among multiple domains while the variables store can't. Michal Privoznik (3): conf: Extend <loader/> and introduce <nvram/> qemu: Implement extended loader and nvram qemu: Automatically create NVRAM store configure.ac | 27 +++++ docs/formatdomain.html.in | 19 +++- docs/schemas/domaincommon.rng | 21 ++++ libvirt.spec.in | 2 + src/Makefile.am | 1 + src/conf/domain_conf.c | 87 +++++++++++++- src/conf/domain_conf.h | 22 +++- src/libvirt_private.syms | 3 + src/qemu/libvirtd_qemu.aug | 3 + src/qemu/qemu.conf | 9 ++ src/qemu/qemu_command.c | 87 +++++++++++++- src/qemu/qemu_conf.c | 8 ++ src/qemu/qemu_conf.h | 3 + src/qemu/qemu_process.c | 125 +++++++++++++++++++++ src/qemu/test_libvirtd_qemu.aug.in | 1 + src/security/security_dac.c | 8 ++ src/security/security_selinux.c | 8 ++ src/security/virt-aa-helper.c | 4 +- src/vbox/vbox_tmpl.c | 7 +- src/xenapi/xenapi_driver.c | 3 +- src/xenxs/xen_sxpr.c | 16 +-- src/xenxs/xen_xm.c | 8 +- .../qemuxml2argvdata/qemuxml2argv-bios-nvram.args | 10 ++ tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml | 40 +++++++ tests/qemuxml2argvtest.c | 2 + .../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 +- 82 files changed, 556 insertions(+), 82 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml -- 1.8.5.5

Up to now, users can configure BIOS via the <loader/> 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: <nvram/>. Currently, it has no additional attributes, it's just a bare element containing path to the variable store file. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- 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_tmpl.c | 7 +- src/xenapi/xenapi_driver.c | 3 +- src/xenxs/xen_sxpr.c | 16 ++-- src/xenxs/xen_xm.c | 8 +- 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, 270 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 418120e..7c569d2 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'/> @@ -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. <span class="since">Xen since 0.1.0, - QEMU/KVM since 0.9.12</span></dd> + QEMU/KVM since 0.9.12</span> Then, <span class="since">Since + 1.2.8</span> it's possible for the element to have two + optional attributes: <code>readonly</code> (accepted values are + <code>on</code> and <code>off</code>) to reflect the fact that the + image should be writable or read-only. The second attribute + <code>type</code> accepts values <code>rom</code> and + <code>pflash</code>. 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, <code>type</code> should be + <code>pflash</code>.</dd> + <dt><code>nvram</code></dt> + <dd>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. <span class="since">Since + 1.2.8</span></dd> <dt><code>boot</code></dt> <dd>The <code>dev</code> 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 b7a1b6f..f4383c2 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -242,6 +242,27 @@ <interleave> <optional> <element name="loader"> + <optional> + <attribute name="readonly"> + <choice> + <value>on</value> + <value>off</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="type"> + <choice> + <value>rom</value> + <value>pflash</value> + </choice> + </attribute> + </optional> + <ref name="absFilePath"/> + </element> + </optional> + <optional> + <element name="nvram"> <ref name="absFilePath"/> </element> </optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d87ca24..53f0e83 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -758,6 +758,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 * <mirror> XML (remaining types are not two-phase). */ VIR_ENUM_DECL(virDomainBlockJob) @@ -1991,6 +1996,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; @@ -2096,7 +2112,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); @@ -11584,6 +11600,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 = virTristateSwitchTypeFromString(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, @@ -12566,12 +12618,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")) { @@ -17611,6 +17673,23 @@ virDomainHugepagesFormat(virBufferPtr buf, virBufferAddLit(buf, "</hugepages>\n"); } +static void +virDomainLoaderDefFormat(virBufferPtr buf, + virDomainLoaderDefPtr loader) +{ + const char *readonly = virTristateSwitchTypeToString(loader->readonly); + const char *type = virDomainLoaderTypeToString(loader->type); + + virBufferAddLit(buf, "<loader"); + + if (loader->readonly) + virBufferAsprintf(buf, " readonly='%s'", readonly); + + virBufferAsprintf(buf, " type='%s'>", type); + + virBufferEscapeString(buf, "%s</loader>\n", loader->path); + virBufferEscapeString(buf, "<nvram>%s</nvram>\n", loader->nvram); +} #define DUMPXML_FLAGS \ (VIR_DOMAIN_XML_SECURE | \ @@ -17940,8 +18019,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, for (i = 0; def->os.initargv && def->os.initargv[i]; i++) virBufferEscapeString(buf, "<initarg>%s</initarg>\n", def->os.initargv[i]); - virBufferEscapeString(buf, "<loader>%s</loader>\n", - def->os.loader); + if (def->os.loader) + virDomainLoaderDefFormat(buf, def->os.loader); virBufferEscapeString(buf, "<kernel>%s</kernel>\n", def->os.kernel); virBufferEscapeString(buf, "<initrd>%s</initrd>\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index bffc0a5..19b05f4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1619,6 +1619,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 virTristateSwitch */ + 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; @@ -1636,7 +1656,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 08111d4..dd4c46f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -312,6 +312,9 @@ virDomainLifecycleCrashTypeToString; virDomainLifecycleTypeFromString; virDomainLifecycleTypeToString; virDomainLiveConfigHelperMethod; +virDomainLoaderDefFree; +virDomainLoaderTypeFromString; +virDomainLoaderTypeToString; virDomainLockFailureTypeFromString; virDomainLockFailureTypeToString; virDomainMemballoonModelTypeFromString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 033a5a8..a3c048f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7441,7 +7441,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 @@ -11231,7 +11231,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 f25a7df7..fde0e5d 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_tmpl.c b/src/vbox/vbox_tmpl.c index ccba736..3233058 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3852,7 +3852,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); + VIR_DEBUG("def->os.loader %p", 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.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 5bcfd29..4af1b95 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/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index 610b7e4..97695b4 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/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/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index 4461654..d2f761d 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -310,7 +310,9 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, if (hvm) { const char *boot; - if (xenXMConfigCopyString(conf, "kernel", &def->os.loader) < 0) + if (VIR_ALLOC(def->os.loader) < 0) + goto cleanup; + if (xenXMConfigCopyString(conf, "kernel", &def->os.loader->path) < 0) goto cleanup; if (xenXMConfigGetString(conf, "boot", &boot, "c") < 0) @@ -1559,8 +1561,8 @@ virConfPtr xenFormatXM(virConnectPtr conn, if (xenXMConfigSetString(conf, "builder", "hvm") < 0) goto cleanup; - 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) goto cleanup; for (i = 0; i < def->os.nBootDevs; i++) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml new file mode 100644 index 0000000..d497010 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>test-bios</name> + <uuid>362d1fc1-df7d-193e-5c18-49a71bd1da66</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <loader readonly='on' type='pflash'>/usr/share/OVMF/OVMF_CODE.fd</loader> + <nvram>/usr/share/OVMF/OVMF_VARS.fd</nvram> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <features> + <acpi/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='tablet' bus='usb'/> + <memballoon model='virtio'/> + </devices> +</domain> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='x86_64' machine='pc-i440fx-1.4'>hvm</type> - <loader>/usr/share/seabios/bios.bin</loader> + <loader type='rom'>/usr/share/seabios/bios.bin</loader> <boot dev='hd'/> </os> <features> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7d416d0..5bf1a5f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -387,6 +387,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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>2</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_... </cmdline> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader&test</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader&test</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='cdrom'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> 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 @@ <vcpu placement='static'>1</vcpu> <os> <type arch='i686' machine='xenfv'>hvm</type> - <loader>/usr/lib/xen/boot/hvmloader</loader> + <loader type='rom'>/usr/lib/xen/boot/hvmloader</loader> <boot dev='hd'/> </os> <features> -- 1.8.5.5

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 <loader> and the second one <nvram>. Moreover, these two lines obsoletes 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 <mprivozn@redhat.com> --- src/qemu/qemu_command.c | 84 ++++++++++++++++++++-- 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, 108 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 a3c048f..982dd7b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7284,6 +7284,84 @@ qemuBuildChrDeviceCommandLine(virCommandPtr cmd, return 0; } +static int +qemuBuilDomainLoaderCommandLine(virCommandPtr cmd, + virDomainDefPtr def, + virQEMUCapsPtr qemuCaps) +{ + int ret = -1; + virDomainLoaderDefPtr loader = def->os.loader; + virBuffer buf = VIR_BUFFER_INITIALIZER; + + 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: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this qemu doesn't support -drive")); + goto cleanup; + } + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this qemu 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=0", + loader->path); + + 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=1", + loader->nvram); + + 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, }; @@ -7439,10 +7517,8 @@ qemuBuildCommandLine(virConnectPtr conn, virCommandAddArg(cmd, "-enable-nesting"); } - if (def->os.loader) { - virCommandAddArg(cmd, "-bios"); - virCommandAddArg(cmd, def->os.loader->path); - } + if (qemuBuilDomainLoaderCommandLine(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 609c1bc..0dd1a27 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -636,6 +636,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); -- 1.8.5.5

Il 08/08/2014 12:17, Michal Privoznik ha scritto:
+ if (loader->nvram) { + virBufferFreeAndReset(&buf); + virBufferAsprintf(&buf, + "file=%s,if=pflash,format=raw,unit=1", + loader->nvram); + + virCommandAddArg(cmd, "-drive"); + virCommandAddArgBuffer(cmd, &buf); + }
Note that other machines may not need unit=1, for example pseries doesn't need it (it uses -bios for the firmware, not -drive if=pflash). It would be nice to make this easily configurable. Alternatively you could use unit=1 if there is a <loader type='pflash'> element, and unit=0 otherwise. We can then patch QEMU to reject unit=1 on machines that use -bios + -drive if=pflash,unit=0. Laszlo, what happens on x86 with -bios + -drive if=pflash,unit=0? Paolo

On 08.08.2014 14:08, Paolo Bonzini wrote:
Il 08/08/2014 12:17, Michal Privoznik ha scritto:
+ if (loader->nvram) { + virBufferFreeAndReset(&buf); + virBufferAsprintf(&buf, + "file=%s,if=pflash,format=raw,unit=1", + loader->nvram); + + virCommandAddArg(cmd, "-drive"); + virCommandAddArgBuffer(cmd, &buf); + }
Note that other machines may not need unit=1, for example pseries doesn't need it (it uses -bios for the firmware, not -drive if=pflash). It would be nice to make this easily configurable.
Is there a table anywhere where I can see what machine types support this? Or does it makes sense to enable this only for qemu-system-{x86_64,i386} -M pc and error out for all other combinations?
Alternatively you could use unit=1 if there is a <loader type='pflash'> element, and unit=0 otherwise. We can then patch QEMU to reject unit=1 on machines that use -bios + -drive if=pflash,unit=0.
Laszlo, what happens on x86 with -bios + -drive if=pflash,unit=0?
Paolo
Michal

Il 08/08/2014 14:26, Michal Privoznik ha scritto:
Note that other machines may not need unit=1, for example pseries doesn't need it (it uses -bios for the firmware, not -drive if=pflash). It would be nice to make this easily configurable.
Is there a table anywhere where I can see what machine types support this? Or does it makes sense to enable this only for qemu-system-{x86_64,i386} -M pc and error out for all other combinations?
Only on x86_64 is a good match for now. I don't know what ARM does or will do, but it's possible it supports or will support 2 pflash devices too. Paolo

On 08/08/14 14:08, Paolo Bonzini wrote:
Il 08/08/2014 12:17, Michal Privoznik ha scritto:
+ if (loader->nvram) { + virBufferFreeAndReset(&buf); + virBufferAsprintf(&buf, + "file=%s,if=pflash,format=raw,unit=1", + loader->nvram); + + virCommandAddArg(cmd, "-drive"); + virCommandAddArgBuffer(cmd, &buf); + }
Note that other machines may not need unit=1, for example pseries doesn't need it (it uses -bios for the firmware, not -drive if=pflash). It would be nice to make this easily configurable.
Alternatively you could use unit=1 if there is a <loader type='pflash'> element, and unit=0 otherwise. We can then patch QEMU to reject unit=1 on machines that use -bios + -drive if=pflash,unit=0.
Laszlo, what happens on x86 with -bios + -drive if=pflash,unit=0?
I checked that earlier (independently of unit=... in the pflash drive). With -bios, you only change the bios filename: case QEMU_OPTION_bios: qemu_opts_set(qemu_find_opts("machine"), 0, "firmware", optarg); [...] bios_name = qemu_opt_get(machine_opts, "firmware"); Code using bios_name is not reached when a pflash drive is present: that would be old_pc_system_rom_init() in "hw/i386/pc_sysfw.c", but its only caller, pc_system_firmware_init(), doesn't call it if there's at least one pflash drive (and you're not running an ISA PC). ... I did find the "firmware" machine property too, but it seems to be used only on s390x. So, in total, as long as you run a PCI-enabled PC (esp. i440fx) machine type, -bios is simply ignored when a pflash drive is present. Thanks Laszlo

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 and the default path can be compiled in via --with-qemu-nvram-file configure option. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- configure.ac | 27 ++++++++ libvirt.spec.in | 2 + src/Makefile.am | 1 + src/qemu/libvirtd_qemu.aug | 3 + src/qemu/qemu.conf | 9 +++ src/qemu/qemu_conf.c | 8 +++ src/qemu/qemu_conf.h | 3 + src/qemu/qemu_process.c | 125 +++++++++++++++++++++++++++++++++++++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 9 files changed, 179 insertions(+) diff --git a/configure.ac b/configure.ac index 9dd07d2..16ca266 100644 --- a/configure.ac +++ b/configure.ac @@ -569,6 +569,11 @@ AC_ARG_WITH([chrdev-lock-files], [location for UUCP style lock files for character devices (use auto for default paths on some platforms) @<:@default=auto@:>@])]) m4_divert_text([DEFAULTS], [with_chrdev_lock_files=auto]) +AC_ARG_WITH([qemu-nvram-file], + [AS_HELP_STRING([--with-qemu-nvram-file], + [location of OVMF_VARS.fd file + (use auto for default path on some platforms) @<:@default=auto@:>@])]) +m4_divert_text([DEFAULTS], [with_qemu_nvram_file=auto]) AC_ARG_WITH([pm-utils], [AS_HELP_STRING([--with-pm-utils], [use pm-utils for power management @<:@default=yes@:>@])]) @@ -1418,6 +1423,27 @@ platform]) fi AM_CONDITIONAL([VIR_CHRDEV_LOCK_FILE_PATH], [test "$with_chrdev_lock_files" != "no"]) +dnl OVMF_VARS.fd file +if test "$with_qemu_nvram_file" != "no"; then + case $with_qemu_nvram_file in + yes | auto) + dnl Default locations for platforms, or disable if unknown + if test "$with_linux" = "yes"; then + with_qemu_nvram_file=/usr/share/OVMF/OVMF_VARS.fd + elif test "$with_chrdev_lock_files" = "auto"; then + with_qemu_nvram_file=no + fi ;; + esac + if test "$with_qemu_nvram_file" = "yes"; then + AC_MSG_ERROR([You must specify path for the lock files on this +platform]) + fi + if test "$with_qemu_nvram_file" != "no"; then + AC_DEFINE_UNQUOTED([VIR_QEMU_NVRAM_FILE_PATH], "$with_qemu_nvram_file", + [default path to OVMF_VARS.fd file]) + fi +fi +AM_CONDITIONAL([VIR_QEMU_NVRAM_FILE_PATH], [test "$with_qemu_nvram_file" != "no"]) AC_ARG_WITH([secdriver-selinux], [AS_HELP_STRING([--with-secdriver-selinux], @@ -2925,6 +2951,7 @@ AC_MSG_NOTICE([ numad: $with_numad]) AC_MSG_NOTICE([ XML Catalog: $XML_CATALOG_FILE]) AC_MSG_NOTICE([ Init script: $with_init_script]) AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files]) +AC_MSG_NOTICE([ OVMF_VARS.fd loc: $with_qemu_nvram_file]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([Developer Tools]) AC_MSG_NOTICE([]) diff --git a/libvirt.spec.in b/libvirt.spec.in index 29da071..486fc66 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1947,6 +1947,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 @@ -2049,6 +2050,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 982f63d..9bd38f5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2632,6 +2632,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/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index e7db7fe..3d9db99 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_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..a0c9485 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -487,3 +487,12 @@ # 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. +#nvram = "/usr/share/OVMF/OVMF_VARS.fd" diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6bfa48e..3f6d365 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -255,6 +255,11 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged) cfg->logTimestamp = true; +#ifdef VIR_QEMU_NVRAM_FILE_PATH + if (VIR_STRDUP(cfg->nvram, VIR_QEMU_NVRAM_FILE_PATH) < 0) + goto error; +#endif + return cfg; error: @@ -305,6 +310,7 @@ static void virQEMUDriverConfigDispose(void *obj) virStringFreeList(cfg->securityDriverNames); VIR_FREE(cfg->lockManagerName); + VIR_FREE(cfg->nvram); } @@ -654,6 +660,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp); + GET_VALUE_STR("nvram", cfg->nvram); + ret = 0; cleanup: diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 90aebef..0bb5333 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -172,6 +172,9 @@ struct _virQEMUDriverConfig { int migrationPortMax; bool logTimestamp; + + char *nvram; /* path to master NVRAM file from which + copies per domain are derived */ }; /* Main driver state */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 407da5e..2cb693a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -66,6 +66,7 @@ #include "virnuma.h" #include "virstring.h" #include "virhostdev.h" +#include "configmake.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -3714,6 +3715,123 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm) } +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; + + /* 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)) { + ssize_t r = -1; + + if (!cfg->nvram) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("master NVRAM file is not configured " + "or turned off by administrator")); + goto cleanup; + } + + if ((srcFD = virFileOpenAs(cfg->nvram, O_RDONLY, + 0, -1, -1, 0)) < 0) { + virReportSystemError(-srcFD, + _("Failed to open file '%s'"), + cfg->nvram); + 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; + } + + while (r) { + char buf[1024]; + ssize_t w = 0; + + if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) { + virReportSystemError(errno, + _("Unable to read from file '%s'"), + cfg->nvram); + goto cleanup; + } + + do { + ssize_t actW; + if ((actW = safewrite(dstFD, buf + w, r - w)) < 0) { + virReportSystemError(errno, + _("Unable to write to file '%s'"), + loader->nvram); + goto cleanup; + } + w += actW; + } while (w != r); + } + + if (VIR_CLOSE(srcFD) < 0) { + virReportSystemError(errno, + _("Unable to close file '%s'"), + cfg->nvram); + 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 && generated) + VIR_FREE(loader->nvram); + + VIR_FORCE_CLOSE(srcFD); + VIR_FORCE_CLOSE(dstFD); + return ret; +} + + int qemuProcessStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -3781,6 +3899,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..1ecb690 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -74,3 +74,4 @@ module Test_libvirtd_qemu = { "migration_port_min" = "49152" } { "migration_port_max" = "49215" } { "log_timestamp" = "0" } +{ "nvram" = "/usr/share/OVMF/OVMF_VARS.fd" } -- 1.8.5.5

Il 08/08/2014 12:17, Michal Privoznik ha scritto:
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 and the default path can be compiled in via --with-qemu-nvram-file configure option.
The only problem I see with this series is in this patch. The master _VARS file can be different for different machine types, for different architectures, and even for different _CODE files. Perhaps you could introduce a format='...' attribute in <nvram> and use that to pick the right master file (e.g. a format value could be uefi128k)? I don't like it, but I cannot think of anything else. Or just leave out this patch for now... Paolo
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- configure.ac | 27 ++++++++ libvirt.spec.in | 2 + src/Makefile.am | 1 + src/qemu/libvirtd_qemu.aug | 3 + src/qemu/qemu.conf | 9 +++ src/qemu/qemu_conf.c | 8 +++ src/qemu/qemu_conf.h | 3 + src/qemu/qemu_process.c | 125 +++++++++++++++++++++++++++++++++++++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 9 files changed, 179 insertions(+)
diff --git a/configure.ac b/configure.ac index 9dd07d2..16ca266 100644 --- a/configure.ac +++ b/configure.ac @@ -569,6 +569,11 @@ AC_ARG_WITH([chrdev-lock-files], [location for UUCP style lock files for character devices (use auto for default paths on some platforms) @<:@default=auto@:>@])]) m4_divert_text([DEFAULTS], [with_chrdev_lock_files=auto]) +AC_ARG_WITH([qemu-nvram-file], + [AS_HELP_STRING([--with-qemu-nvram-file], + [location of OVMF_VARS.fd file + (use auto for default path on some platforms) @<:@default=auto@:>@])]) +m4_divert_text([DEFAULTS], [with_qemu_nvram_file=auto]) AC_ARG_WITH([pm-utils], [AS_HELP_STRING([--with-pm-utils], [use pm-utils for power management @<:@default=yes@:>@])]) @@ -1418,6 +1423,27 @@ platform]) fi AM_CONDITIONAL([VIR_CHRDEV_LOCK_FILE_PATH], [test "$with_chrdev_lock_files" != "no"])
+dnl OVMF_VARS.fd file +if test "$with_qemu_nvram_file" != "no"; then + case $with_qemu_nvram_file in + yes | auto) + dnl Default locations for platforms, or disable if unknown + if test "$with_linux" = "yes"; then + with_qemu_nvram_file=/usr/share/OVMF/OVMF_VARS.fd + elif test "$with_chrdev_lock_files" = "auto"; then + with_qemu_nvram_file=no + fi ;; + esac + if test "$with_qemu_nvram_file" = "yes"; then + AC_MSG_ERROR([You must specify path for the lock files on this +platform]) + fi + if test "$with_qemu_nvram_file" != "no"; then + AC_DEFINE_UNQUOTED([VIR_QEMU_NVRAM_FILE_PATH], "$with_qemu_nvram_file", + [default path to OVMF_VARS.fd file]) + fi +fi +AM_CONDITIONAL([VIR_QEMU_NVRAM_FILE_PATH], [test "$with_qemu_nvram_file" != "no"])
AC_ARG_WITH([secdriver-selinux], [AS_HELP_STRING([--with-secdriver-selinux], @@ -2925,6 +2951,7 @@ AC_MSG_NOTICE([ numad: $with_numad]) AC_MSG_NOTICE([ XML Catalog: $XML_CATALOG_FILE]) AC_MSG_NOTICE([ Init script: $with_init_script]) AC_MSG_NOTICE([Char device locks: $with_chrdev_lock_files]) +AC_MSG_NOTICE([ OVMF_VARS.fd loc: $with_qemu_nvram_file]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([Developer Tools]) AC_MSG_NOTICE([]) diff --git a/libvirt.spec.in b/libvirt.spec.in index 29da071..486fc66 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -1947,6 +1947,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 @@ -2049,6 +2050,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 982f63d..9bd38f5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2632,6 +2632,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/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index e7db7fe..3d9db99 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_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..a0c9485 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -487,3 +487,12 @@ # 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. +#nvram = "/usr/share/OVMF/OVMF_VARS.fd" diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 6bfa48e..3f6d365 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -255,6 +255,11 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
cfg->logTimestamp = true;
+#ifdef VIR_QEMU_NVRAM_FILE_PATH + if (VIR_STRDUP(cfg->nvram, VIR_QEMU_NVRAM_FILE_PATH) < 0) + goto error; +#endif + return cfg;
error: @@ -305,6 +310,7 @@ static void virQEMUDriverConfigDispose(void *obj) virStringFreeList(cfg->securityDriverNames);
VIR_FREE(cfg->lockManagerName); + VIR_FREE(cfg->nvram); }
@@ -654,6 +660,8 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp);
+ GET_VALUE_STR("nvram", cfg->nvram); + ret = 0;
cleanup: diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 90aebef..0bb5333 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -172,6 +172,9 @@ struct _virQEMUDriverConfig { int migrationPortMax;
bool logTimestamp; + + char *nvram; /* path to master NVRAM file from which + copies per domain are derived */ };
/* Main driver state */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 407da5e..2cb693a 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -66,6 +66,7 @@ #include "virnuma.h" #include "virstring.h" #include "virhostdev.h" +#include "configmake.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3714,6 +3715,123 @@ qemuProcessVerifyGuestCPU(virQEMUDriverPtr driver, virDomainObjPtr vm) }
+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; + + /* 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)) { + ssize_t r = -1; + + if (!cfg->nvram) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("master NVRAM file is not configured " + "or turned off by administrator")); + goto cleanup; + } + + if ((srcFD = virFileOpenAs(cfg->nvram, O_RDONLY, + 0, -1, -1, 0)) < 0) { + virReportSystemError(-srcFD, + _("Failed to open file '%s'"), + cfg->nvram); + 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; + } + + while (r) { + char buf[1024]; + ssize_t w = 0; + + if ((r = saferead(srcFD, buf, sizeof(buf))) < 0) { + virReportSystemError(errno, + _("Unable to read from file '%s'"), + cfg->nvram); + goto cleanup; + } + + do { + ssize_t actW; + if ((actW = safewrite(dstFD, buf + w, r - w)) < 0) { + virReportSystemError(errno, + _("Unable to write to file '%s'"), + loader->nvram); + goto cleanup; + } + w += actW; + } while (w != r); + } + + if (VIR_CLOSE(srcFD) < 0) { + virReportSystemError(errno, + _("Unable to close file '%s'"), + cfg->nvram); + 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 && generated) + VIR_FREE(loader->nvram); + + VIR_FORCE_CLOSE(srcFD); + VIR_FORCE_CLOSE(dstFD); + return ret; +} + + int qemuProcessStart(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -3781,6 +3899,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..1ecb690 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -74,3 +74,4 @@ module Test_libvirtd_qemu = { "migration_port_min" = "49152" } { "migration_port_max" = "49215" } { "log_timestamp" = "0" } +{ "nvram" = "/usr/share/OVMF/OVMF_VARS.fd" }

On 08/08/14 14:05, Paolo Bonzini wrote:
Il 08/08/2014 12:17, Michal Privoznik ha scritto:
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 and the default path can be compiled in via --with-qemu-nvram-file configure option.
The only problem I see with this series is in this patch.
The master _VARS file can be different for different machine types, for different architectures, and even for different _CODE files.
(I wasn't CC'd on the patch series, and I'm not a subscriber either, but I now imported the set from the archive and hopefully can reply in-thread.) So, my suggestion was, for "src/qemu/qemu.conf": # Locations of master nvram files # # 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. # # Different firmware binaries can have different nvram templates; # the following list specifies the mapping. Separate the # nvram template from the firmware binary with a colon (":"). # # nvram = [ "/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd" ] Michal then asked if we should maybe even say: nvram = [ "x86_64:/usr/share/OVMF/OVMF_CODE.fd:/usr/share/OVMF/OVMF_VARS.fd", "i686:/usr/share/OVMF32/OVMF_CODE.fd:/usr/share/OVMF32/OVMF_VARS.fd" ] I don't think so. "x86_64:/usr/share/OVMF/OVMF_CODE.fd" does not carry more information than just "/usr/share/OVMF/OVMF_CODE.fd". The firmware binary itself determines the valid architectures and the nvram template; there's no additional "degree of freedom" in that selection. That is, we do NOT have: (guest architecture, firmware binary) --> nvram template instead we have: firmware binary --> ( { set of valid architectures / machtypes }, nvram template ) It is the user's responsibility to match architecture (machine type) and firmware binary in the domain XML against each other. - If they specify a firmware binary that is wrong for the architecture, the firmware simply won't run. (No different from trying to boot an OS that doesn't match the architecture.) - If they specify the correct firmware binary, then it's *only* the firmware binary that libvirt needs to look at, in order to determine the nvram template. Thanks, Laszlo
participants (3)
-
Laszlo Ersek
-
Michal Privoznik
-
Paolo Bonzini