2014-09-23 21:27:47 +00:00
|
|
|
From b1a7618b73c8463dba00e6afe252b6c05fa3d89c Mon Sep 17 00:00:00 2001
|
2014-09-18 19:36:06 +00:00
|
|
|
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
|
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 <loader> and the second one <nvram>.
|
|
|
|
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 <mprivozn@redhat.com>
|
|
|
|
Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
|
(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);
|