On 03/07/19 10:29, Michal Privoznik wrote:
Test firmware description parsing so far.
The test files come from three locations:
1) ovmf-sb-keys.json and ovmf-sb.json come from OVMF
package from RHEL-7 (with slight name change to reflect their
features in filename too),
2) bios.json and aavmf.json come form comments from
(a) s/form/from/
(b) s/comments/example JSON documents/ -- I'm emphasizing this because
QEMU itself is pretty strict about calling those comment sections
"Examples".
firmware.json from qemu's git (3a0adfc9bf),
3) ovmf.json is then copied from ovmf-sb.json and stripped
of SECURE_BOOT and REQUIRES_SMM flags (plus OVMF path change).
The way you derived "ovmf.json" from "ovmf-sb.json" is not bad, but
it
should be improved. I'll make comments on the file itself, below.
(c) Please don't forget to update this section of the commit message in
sync.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
tests/Makefile.am | 9 +++
tests/qemufirmwaredata/aavmf.json | 35 +++++++++++
tests/qemufirmwaredata/bios.json | 35 +++++++++++
tests/qemufirmwaredata/ovmf-sb-keys.json | 36 ++++++++++++
tests/qemufirmwaredata/ovmf-sb.json | 35 +++++++++++
tests/qemufirmwaredata/ovmf.json | 33 +++++++++++
tests/qemufirmwaretest.c | 75 ++++++++++++++++++++++++
7 files changed, 258 insertions(+)
create mode 100644 tests/qemufirmwaredata/aavmf.json
create mode 100644 tests/qemufirmwaredata/bios.json
create mode 100644 tests/qemufirmwaredata/ovmf-sb-keys.json
create mode 100644 tests/qemufirmwaredata/ovmf-sb.json
create mode 100644 tests/qemufirmwaredata/ovmf.json
create mode 100644 tests/qemufirmwaretest.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 72f0420bab..b3449fa96b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -132,6 +132,7 @@ EXTRA_DIST = \
qemuxml2xmloutdata \
qemustatusxml2xmldata \
qemumemlockdata \
+ qemufirmwaredata \
secretxml2xmlin \
securityselinuxhelperdata \
securityselinuxlabeldata \
@@ -292,6 +293,7 @@ test_programs += qemuxml2argvtest qemuxml2xmltest \
qemublocktest \
qemumigparamstest \
qemusecuritytest \
+ qemufirmwaretest \
$(NULL)
test_helpers += qemucapsprobe
test_libraries += libqemumonitortestutils.la \
@@ -700,6 +702,12 @@ qemusecuritytest_SOURCES = \
testutilsqemu.h testutilsqemu.c
qemusecuritytest_LDADD = $(qemu_LDADDS) $(LDADDS)
+qemufirmwaretest_SOURCES = \
+ qemufirmwaretest.c \
+ testutils.h testutils.c \
+ $(NULL)
+qemufirmwaretest_LDADD = $(qemu_LDADDS) $(LDADDS)
+
else ! WITH_QEMU
EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \
domainsnapshotxml2xmltest.c \
@@ -713,6 +721,7 @@ EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c
\
qemumigparamstest.c \
qemusecuritytest.c qemusecuritytest.h \
qemusecuritymock.c \
+ qemufirmwaretest.c \
$(QEMUMONITORTESTUTILS_SOURCES)
endif ! WITH_QEMU
diff --git a/tests/qemufirmwaredata/aavmf.json b/tests/qemufirmwaredata/aavmf.json
new file mode 100644
index 0000000000..114d1475a2
--- /dev/null
+++ b/tests/qemufirmwaredata/aavmf.json
@@ -0,0 +1,35 @@
+{
+ "description": "UEFI firmware for ARM64 virtual machines",
+ "interface-types": [
+ "uefi"
+ ],
+ "mapping": {
+ "device": "flash",
+ "executable": {
+ "filename": "/usr/share/AAVMF/AAVMF_CODE.fd",
+ "format": "raw"
+ },
+ "nvram-template": {
+ "filename": "/usr/share/AAVMF/AAVMF_VARS.fd",
+ "format": "raw"
+ }
+ },
+ "targets": [
+ {
+ "architecture": "aarch64",
+ "machines": [
+ "virt-*"
+ ]
+ }
+ ],
+ "features": [
+
+ ],
+ "tags": [
+ "-a AARCH64",
+ "-p ArmVirtPkg/ArmVirtQemu.dsc",
+ "-t GCC48",
+ "-b DEBUG",
+ "-D DEBUG_PRINT_ERROR_LEVEL=0x80000000"
+ ]
+}
diff --git a/tests/qemufirmwaredata/bios.json b/tests/qemufirmwaredata/bios.json
new file mode 100644
index 0000000000..137ff70779
--- /dev/null
+++ b/tests/qemufirmwaredata/bios.json
@@ -0,0 +1,35 @@
+{
+ "description": "SeaBIOS",
+ "interface-types": [
+ "bios"
+ ],
+ "mapping": {
+ "device": "memory",
+ "filename": "/usr/share/seabios/bios-256k.bin"
+ },
+ "targets": [
+ {
+ "architecture": "i386",
+ "machines": [
+ "pc-i440fx-*",
+ "pc-q35-*"
+ ]
+ },
+ {
+ "architecture": "x86_64",
+ "machines": [
+ "pc-i440fx-*",
+ "pc-q35-*"
+ ]
+ }
+ ],
+ "features": [
+ "acpi-s3",
+ "acpi-s4"
+ ],
+ "tags": [
+ "CONFIG_BOOTSPLASH=n",
+ "CONFIG_ROM_SIZE=256",
+ "CONFIG_USE_SMM=n"
+ ]
+}
diff --git a/tests/qemufirmwaredata/ovmf-sb-keys.json
b/tests/qemufirmwaredata/ovmf-sb-keys.json
new file mode 100644
index 0000000000..c804ac1038
--- /dev/null
+++ b/tests/qemufirmwaredata/ovmf-sb-keys.json
@@ -0,0 +1,36 @@
+{
+ "description": "OVMF with SB+SMM, SB enabled, MS certs
enrolled",
+ "interface-types": [
+ "uefi"
+ ],
+ "mapping": {
+ "device": "flash",
+ "executable": {
+ "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd",
+ "format": "raw"
+ },
+ "nvram-template": {
+ "filename": "/usr/share/OVMF/OVMF_VARS.secboot.fd",
+ "format": "raw"
+ }
+ },
+ "targets": [
+ {
+ "architecture": "x86_64",
+ "machines": [
+ "pc-q35-*"
+ ]
+ }
+ ],
+ "features": [
+ "acpi-s3",
+ "amd-sev",
+ "enrolled-keys",
+ "requires-smm",
+ "secure-boot",
+ "verbose-dynamic"
+ ],
+ "tags": [
+
+ ]
+}
diff --git a/tests/qemufirmwaredata/ovmf-sb.json b/tests/qemufirmwaredata/ovmf-sb.json
new file mode 100644
index 0000000000..5e8a94ae78
--- /dev/null
+++ b/tests/qemufirmwaredata/ovmf-sb.json
@@ -0,0 +1,35 @@
+{
+ "description": "OVMF with SB+SMM, empty varstore",
+ "interface-types": [
+ "uefi"
+ ],
+ "mapping": {
+ "device": "flash",
+ "executable": {
+ "filename": "/usr/share/OVMF/OVMF_CODE.secboot.fd",
+ "format": "raw"
+ },
+ "nvram-template": {
+ "filename": "/usr/share/OVMF/OVMF_VARS.fd",
+ "format": "raw"
+ }
+ },
+ "targets": [
+ {
+ "architecture": "x86_64",
+ "machines": [
+ "pc-q35-*"
+ ]
+ }
+ ],
+ "features": [
+ "acpi-s3",
+ "amd-sev",
+ "requires-smm",
+ "secure-boot",
+ "verbose-dynamic"
+ ],
+ "tags": [
+
+ ]
+}
diff --git a/tests/qemufirmwaredata/ovmf.json b/tests/qemufirmwaredata/ovmf.json
new file mode 100644
index 0000000000..9d53094778
--- /dev/null
+++ b/tests/qemufirmwaredata/ovmf.json
@@ -0,0 +1,33 @@
+{
+ "description": "OVMF with SB+SMM, empty varstore",
"SB", "SMM", and "empty varstore" are each either wrong or
useless to
mention here.
(d) So I suggest retrofitting the AAVMF description instead -- just say
"UEFI firmware for x86_64 virtual machines".
+ "interface-types": [
+ "uefi"
+ ],
+ "mapping": {
+ "device": "flash",
+ "executable": {
+ "filename": "/usr/share/OVMF/OVMF_CODE.fd",
+ "format": "raw"
+ },
+ "nvram-template": {
+ "filename": "/usr/share/OVMF/OVMF_VARS.fd",
+ "format": "raw"
+ }
+ },
+ "targets": [
+ {
+ "architecture": "x86_64",
+ "machines": [
+ "pc-q35-*"
(e) Because this build does not include the SMM driver stack, we should
permit "pc-i440fx-*", in addition to "pc-q35-*".
(Points (d) and (e) are not really relevant for the self-test in
libvirt, it's just that the examples should be as "meaningful" as
possible.)
Other than that, thanks for addressing my comments. With the above updates:
Acked-by: Laszlo Ersek <lersek(a)redhat.com>
Thanks
Laszlo
+ ]
+ }
+ ],
+ "features": [
+ "acpi-s3",
+ "amd-sev",
+ "verbose-dynamic"
+ ],
+ "tags": [
+
+ ]
+}
diff --git a/tests/qemufirmwaretest.c b/tests/qemufirmwaretest.c
new file mode 100644
index 0000000000..176cf0920d
--- /dev/null
+++ b/tests/qemufirmwaretest.c
@@ -0,0 +1,75 @@
+#include <config.h>
+
+#include "testutils.h"
+#include "qemu/qemu_firmware.h"
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+/* A very basic test. Parse given JSON firmware description into
+ * an internal structure, format it back and compare with the
+ * contents of the file (minus some keys that are not parsed).
+ */
+static int
+testParseFormatFW(const void *opaque)
+{
+ const char *filename = opaque;
+ VIR_AUTOFREE(char *) path = NULL;
+ VIR_AUTOPTR(qemuFirmware) fw = NULL;
+ VIR_AUTOFREE(char *) buf = NULL;
+ VIR_AUTOPTR(virJSONValue) json = NULL;
+ VIR_AUTOFREE(char *) expected = NULL;
+ VIR_AUTOFREE(char *) actual = NULL;
+
+ if (virAsprintf(&path, "%s/qemufirmwaredata/%s",
+ abs_srcdir, filename) < 0)
+ return -1;
+
+ if (!(fw = qemuFirmwareParse(path)))
+ return -1;
+
+ if (virFileReadAll(path,
+ 1024 * 1024, /* 1MiB */
+ &buf) < 0)
+ return -1;
+
+ if (!(json = virJSONValueFromString(buf)))
+ return -1;
+
+ /* Description and tags are not parsed. */
+ if (virJSONValueObjectRemoveKey(json, "description", NULL) < 0 ||
+ virJSONValueObjectRemoveKey(json, "tags", NULL) < 0)
+ return -1;
+
+ if (!(expected = virJSONValueToString(json, true)))
+ return -1;
+
+ if (!(actual = qemuFirmwareFormat(fw)))
+ return -1;
+
+ return virTestCompareToString(expected, actual);
+}
+
+
+static int
+mymain(void)
+{
+ int ret = 0;
+
+#define DO_PARSE_TEST(filename) \
+ do { \
+ if (virTestRun("QEMU FW " filename, \
+ testParseFormatFW, filename) < 0) \
+ ret = -1; \
+ } while (0)
+
+ DO_PARSE_TEST("bios.json");
+ DO_PARSE_TEST("ovmf-sb-keys.json");
+ DO_PARSE_TEST("ovmf-sb.json");
+ DO_PARSE_TEST("ovmf.json");
+ DO_PARSE_TEST("aavmf.json");
+
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+VIR_TEST_MAIN(mymain);