|
|
3ec523 |
From ac0859aae7162255848effdc560368266845dfce Mon Sep 17 00:00:00 2001
|
|
|
3ec523 |
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
3ec523 |
Date: Thu, 7 Aug 2014 13:50:00 +0200
|
|
|
3ec523 |
Subject: [PATCH] qemu: Implement extended loader and nvram
|
|
|
3ec523 |
|
|
|
3ec523 |
QEMU now supports UEFI with the following command line:
|
|
|
3ec523 |
|
|
|
3ec523 |
-drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \
|
|
|
3ec523 |
-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
|
|
|
3ec523 |
|
|
|
3ec523 |
where the first line reflects <loader> and the second one <nvram>.
|
|
|
3ec523 |
Moreover, these two lines obsolete the -bios argument.
|
|
|
3ec523 |
|
|
|
3ec523 |
Note that UEFI is unusable without ACPI. This is handled properly now.
|
|
|
3ec523 |
Among with this extension, the variable file is expected to be
|
|
|
3ec523 |
writable and hence we need security drivers to label it.
|
|
|
3ec523 |
|
|
|
3ec523 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
3ec523 |
Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
3ec523 |
(cherry picked from commit 542899168c382610dbad9a597d27ef3d7c699f68)
|
|
|
3ec523 |
---
|
|
|
3ec523 |
src/qemu/qemu_command.c | 94 +++++++++++++++++++++-
|
|
|
3ec523 |
src/security/security_dac.c | 8 ++
|
|
|
3ec523 |
src/security/security_selinux.c | 8 ++
|
|
|
3ec523 |
.../qemuxml2argvdata/qemuxml2argv-bios-nvram.args | 10 +++
|
|
|
3ec523 |
tests/qemuxml2argvtest.c | 2 +
|
|
|
3ec523 |
5 files changed, 118 insertions(+), 4 deletions(-)
|
|
|
3ec523 |
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
|
|
|
3ec523 |
|
|
|
3ec523 |
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
|
|
3ec523 |
index 3cb2e0b..718533b 100644
|
|
|
3ec523 |
--- a/src/qemu/qemu_command.c
|
|
|
3ec523 |
+++ b/src/qemu/qemu_command.c
|
|
|
3ec523 |
@@ -7370,6 +7370,94 @@ qemuBuildChrDeviceCommandLine(virCommandPtr cmd,
|
|
|
3ec523 |
return 0;
|
|
|
3ec523 |
}
|
|
|
3ec523 |
|
|
|
3ec523 |
+static int
|
|
|
3ec523 |
+qemuBuildDomainLoaderCommandLine(virCommandPtr cmd,
|
|
|
3ec523 |
+ virDomainDefPtr def,
|
|
|
3ec523 |
+ virQEMUCapsPtr qemuCaps)
|
|
|
3ec523 |
+{
|
|
|
3ec523 |
+ int ret = -1;
|
|
|
3ec523 |
+ virDomainLoaderDefPtr loader = def->os.loader;
|
|
|
3ec523 |
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
3ec523 |
+ int unit = 0;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ if (!loader)
|
|
|
3ec523 |
+ return 0;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ switch ((virDomainLoader) loader->type) {
|
|
|
3ec523 |
+ case VIR_DOMAIN_LOADER_TYPE_ROM:
|
|
|
3ec523 |
+ virCommandAddArg(cmd, "-bios");
|
|
|
3ec523 |
+ virCommandAddArg(cmd, loader->path);
|
|
|
3ec523 |
+ break;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ case VIR_DOMAIN_LOADER_TYPE_PFLASH:
|
|
|
3ec523 |
+ /* UEFI is supported only for x86_64 currently */
|
|
|
3ec523 |
+ if (def->os.arch != VIR_ARCH_X86_64) {
|
|
|
3ec523 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
3ec523 |
+ _("pflash is not supported for %s guest architecture"),
|
|
|
3ec523 |
+ virArchToString(def->os.arch));
|
|
|
3ec523 |
+ goto cleanup;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) {
|
|
|
3ec523 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
3ec523 |
+ _("this QEMU binary doesn't support -drive"));
|
|
|
3ec523 |
+ goto cleanup;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_FORMAT)) {
|
|
|
3ec523 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
3ec523 |
+ _("this QEMU binary doesn't support passing "
|
|
|
3ec523 |
+ "drive format"));
|
|
|
3ec523 |
+ goto cleanup;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NO_ACPI) &&
|
|
|
3ec523 |
+ def->features[VIR_DOMAIN_FEATURE_ACPI] != VIR_TRISTATE_SWITCH_ON) {
|
|
|
3ec523 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
3ec523 |
+ _("ACPI must be enabled in order to use UEFI"));
|
|
|
3ec523 |
+ goto cleanup;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ virBufferAsprintf(&buf,
|
|
|
3ec523 |
+ "file=%s,if=pflash,format=raw,unit=%d",
|
|
|
3ec523 |
+ loader->path, unit);
|
|
|
3ec523 |
+ unit++;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ if (loader->readonly) {
|
|
|
3ec523 |
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) {
|
|
|
3ec523 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
3ec523 |
+ _("this qemu doesn't support passing "
|
|
|
3ec523 |
+ "readonly attribute"));
|
|
|
3ec523 |
+ goto cleanup;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ virBufferAsprintf(&buf, ",readonly=%s",
|
|
|
3ec523 |
+ virTristateSwitchTypeToString(loader->readonly));
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ virCommandAddArg(cmd, "-drive");
|
|
|
3ec523 |
+ virCommandAddArgBuffer(cmd, &buf;;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ if (loader->nvram) {
|
|
|
3ec523 |
+ virBufferFreeAndReset(&buf;;
|
|
|
3ec523 |
+ virBufferAsprintf(&buf,
|
|
|
3ec523 |
+ "file=%s,if=pflash,format=raw,unit=%d",
|
|
|
3ec523 |
+ loader->nvram, unit);
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ virCommandAddArg(cmd, "-drive");
|
|
|
3ec523 |
+ virCommandAddArgBuffer(cmd, &buf;;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+ break;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ case VIR_DOMAIN_LOADER_TYPE_LAST:
|
|
|
3ec523 |
+ /* nada */
|
|
|
3ec523 |
+ break;
|
|
|
3ec523 |
+ }
|
|
|
3ec523 |
+
|
|
|
3ec523 |
+ ret = 0;
|
|
|
3ec523 |
+ cleanup:
|
|
|
3ec523 |
+ virBufferFreeAndReset(&buf;;
|
|
|
3ec523 |
+ return ret;
|
|
|
3ec523 |
+}
|
|
|
3ec523 |
+
|
|
|
3ec523 |
qemuBuildCommandLineCallbacks buildCommandLineCallbacks = {
|
|
|
3ec523 |
.qemuGetSCSIDeviceSgName = virSCSIDeviceGetSgName,
|
|
|
3ec523 |
};
|
|
|
3ec523 |
@@ -7525,10 +7613,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|
|
3ec523 |
virCommandAddArg(cmd, "-enable-nesting");
|
|
|
3ec523 |
}
|
|
|
3ec523 |
|
|
|
3ec523 |
- if (def->os.loader) {
|
|
|
3ec523 |
- virCommandAddArg(cmd, "-bios");
|
|
|
3ec523 |
- virCommandAddArg(cmd, def->os.loader->path);
|
|
|
3ec523 |
- }
|
|
|
3ec523 |
+ if (qemuBuildDomainLoaderCommandLine(cmd, def, qemuCaps) < 0)
|
|
|
3ec523 |
+ goto error;
|
|
|
3ec523 |
|
|
|
3ec523 |
/* Set '-m MB' based on maxmem, because the lower 'memory' limit
|
|
|
3ec523 |
* is set post-startup using the balloon driver. If balloon driver
|
|
|
3ec523 |
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
|
|
|
3ec523 |
index e62828e..e398d2c 100644
|
|
|
3ec523 |
--- a/src/security/security_dac.c
|
|
|
3ec523 |
+++ b/src/security/security_dac.c
|
|
|
3ec523 |
@@ -960,6 +960,10 @@ virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
3ec523 |
rc = -1;
|
|
|
3ec523 |
}
|
|
|
3ec523 |
|
|
|
3ec523 |
+ if (def->os.loader && def->os.loader->nvram &&
|
|
|
3ec523 |
+ virSecurityDACRestoreSecurityFileLabel(def->os.loader->nvram) < 0)
|
|
|
3ec523 |
+ rc = -1;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
if (def->os.kernel &&
|
|
|
3ec523 |
virSecurityDACRestoreSecurityFileLabel(def->os.kernel) < 0)
|
|
|
3ec523 |
rc = -1;
|
|
|
3ec523 |
@@ -1036,6 +1040,10 @@ virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
3ec523 |
if (virSecurityDACGetImageIds(secdef, priv, &user, &group))
|
|
|
3ec523 |
return -1;
|
|
|
3ec523 |
|
|
|
3ec523 |
+ if (def->os.loader && def->os.loader->nvram &&
|
|
|
3ec523 |
+ virSecurityDACSetOwnership(def->os.loader->nvram, user, group) < 0)
|
|
|
3ec523 |
+ return -1;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
if (def->os.kernel &&
|
|
|
3ec523 |
virSecurityDACSetOwnership(def->os.kernel, user, group) < 0)
|
|
|
3ec523 |
return -1;
|
|
|
3ec523 |
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
|
|
|
3ec523 |
index c078cab..a409c19 100644
|
|
|
3ec523 |
--- a/src/security/security_selinux.c
|
|
|
3ec523 |
+++ b/src/security/security_selinux.c
|
|
|
3ec523 |
@@ -1911,6 +1911,10 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
3ec523 |
mgr) < 0)
|
|
|
3ec523 |
rc = -1;
|
|
|
3ec523 |
|
|
|
3ec523 |
+ if (def->os.loader && def->os.loader->nvram &&
|
|
|
3ec523 |
+ virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.loader->nvram) < 0)
|
|
|
3ec523 |
+ rc = -1;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
if (def->os.kernel &&
|
|
|
3ec523 |
virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.kernel) < 0)
|
|
|
3ec523 |
rc = -1;
|
|
|
3ec523 |
@@ -2294,6 +2298,10 @@ virSecuritySELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
3ec523 |
mgr) < 0)
|
|
|
3ec523 |
return -1;
|
|
|
3ec523 |
|
|
|
3ec523 |
+ if (def->os.loader && def->os.loader->nvram &&
|
|
|
3ec523 |
+ virSecuritySELinuxSetFilecon(def->os.loader->nvram, data->content_context) < 0)
|
|
|
3ec523 |
+ return -1;
|
|
|
3ec523 |
+
|
|
|
3ec523 |
if (def->os.kernel &&
|
|
|
3ec523 |
virSecuritySELinuxSetFilecon(def->os.kernel, data->content_context) < 0)
|
|
|
3ec523 |
return -1;
|
|
|
3ec523 |
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
|
|
|
3ec523 |
new file mode 100644
|
|
|
3ec523 |
index 0000000..b51e8f3
|
|
|
3ec523 |
--- /dev/null
|
|
|
3ec523 |
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios-nvram.args
|
|
|
3ec523 |
@@ -0,0 +1,10 @@
|
|
|
3ec523 |
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
|
|
|
3ec523 |
+/usr/bin/qemu -S -M pc \
|
|
|
3ec523 |
+-drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on \
|
|
|
3ec523 |
+-drive file=/usr/share/OVMF/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
|
|
|
3ec523 |
+-m 1024 -smp 1 -nographic -nodefaults \
|
|
|
3ec523 |
+-monitor unix:/tmp/test-monitor,server,nowait -boot c -usb \
|
|
|
3ec523 |
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0,format=raw \
|
|
|
3ec523 |
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
|
|
|
3ec523 |
+-serial pty -device usb-tablet,id=input0 \
|
|
|
3ec523 |
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
|
|
|
3ec523 |
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
|
|
|
3ec523 |
index 3feb2fe..5c28253 100644
|
|
|
3ec523 |
--- a/tests/qemuxml2argvtest.c
|
|
|
3ec523 |
+++ b/tests/qemuxml2argvtest.c
|
|
|
3ec523 |
@@ -642,6 +642,8 @@ mymain(void)
|
|
|
3ec523 |
DO_TEST_FAILURE("reboot-timeout-enabled", NONE);
|
|
|
3ec523 |
|
|
|
3ec523 |
DO_TEST("bios", QEMU_CAPS_DEVICE, QEMU_CAPS_SGA);
|
|
|
3ec523 |
+ DO_TEST("bios-nvram", QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
|
|
|
3ec523 |
+ QEMU_CAPS_DRIVE_FORMAT, QEMU_CAPS_DRIVE_READONLY);
|
|
|
3ec523 |
DO_TEST("clock-utc", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE);
|
|
|
3ec523 |
DO_TEST("clock-localtime", NONE);
|
|
|
3ec523 |
DO_TEST("clock-localtime-basis-localtime", QEMU_CAPS_RTC);
|