[libvirt] [PATCH 0/4] bhyve: UEFI bootrom support

this series of patches adds support for specifying UEFI boot images for bhyve virtual machines. The old behaviour is kept; only when a loader pflash is specified the loader command is omitted and adds a bootrom parameter to the bhyverun command. Fabian Freyer (4): bhyve: Separate out checks from virBhyveProbeCaps bhyve: virBhyveProbeCaps: BHYVE_CAP_LPC_BOOTROM bhyve: add support for booting from UEFI bhyve: Test cases for UEFI bhyvexml2argvtest src/bhyve/bhyve_capabilities.c | 59 ++++++++++++++++++---- src/bhyve/bhyve_capabilities.h | 1 + src/bhyve/bhyve_command.c | 6 +++ src/bhyve/bhyve_driver.c | 27 ++++++++-- tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args | 9 ++++ .../bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs | 1 + tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml | 23 +++++++++ tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args | 10 ++++ tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs | 1 + tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml | 23 +++++++++ tests/bhyvexml2argvtest.c | 13 ++++- 11 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml -- 2.7.0

At the moment this is just one check, but separating this out into a separate function makes checks more modular, allowing for more readable code once more checks are added. This also makes checks more easily testable. --- src/bhyve/bhyve_capabilities.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c index d0af4d9..cf764c0 100644 --- a/src/bhyve/bhyve_capabilities.c +++ b/src/bhyve/bhyve_capabilities.c @@ -142,19 +142,13 @@ virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps) return ret; } -int -virBhyveProbeCaps(unsigned int *caps) +static int +bhyveProbeCapsRTC_UTC(unsigned int *caps, char *binary) { - char *binary, *help; + char *help; virCommandPtr cmd = NULL; int ret = 0, exit; - binary = virFindFileInPath("bhyve"); - if (binary == NULL) - goto out; - if (!virFileIsExecutable(binary)) - goto out; - cmd = virCommandNew(binary); virCommandAddArg(cmd, "-h"); virCommandSetErrorBuffer(cmd, &help); @@ -169,6 +163,25 @@ virBhyveProbeCaps(unsigned int *caps) out: VIR_FREE(help); virCommandFree(cmd); + return ret; +} + +int +virBhyveProbeCaps(unsigned int *caps) +{ + char *binary; + int ret = 0; + + binary = virFindFileInPath("bhyve"); + if (binary == NULL) + goto out; + if (!virFileIsExecutable(binary)) + goto out; + + if ((ret = bhyveProbeCapsRTC_UTC(caps, binary))) + goto out; + + out: VIR_FREE(binary); return ret; } -- 2.7.0

Implement the BHACE_CAP_LPC_BOOTROM capability by checking the stderr output of 'bhyve -l bootrom'. If the bootrom option is unsupported, this will contain the following output: bhyve: invalid lpc device configuration 'bootrom' On newer bhyve versions that do support specifying a bootrom image, the standard help will be printed. --- src/bhyve/bhyve_capabilities.c | 28 ++++++++++++++++++++++++++++ src/bhyve/bhyve_capabilities.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c index cf764c0..5d0485e 100644 --- a/src/bhyve/bhyve_capabilities.c +++ b/src/bhyve/bhyve_capabilities.c @@ -166,6 +166,31 @@ bhyveProbeCapsRTC_UTC(unsigned int *caps, char *binary) return ret; } +static int +bhyveProbeCapsLPC_Bootrom(unsigned int *caps, char *binary) +{ + char *error; + virCommandPtr cmd = NULL; + int ret = 0, exit; + + cmd = virCommandNew(binary); + virCommandAddArgList(cmd, "-l", "bootrom", NULL); + virCommandSetErrorBuffer(cmd, &error); + if (virCommandRun(cmd, &exit) < 0) { + ret = -1; + goto out; + } + + if (strstr(error, "bhyve: invalid lpc device configuration 'bootrom'") == NULL) + *caps |= BHYVE_CAP_LPC_BOOTROM; + + out: + VIR_FREE(error); + virCommandFree(cmd); + return ret; +} + + int virBhyveProbeCaps(unsigned int *caps) { @@ -181,6 +206,9 @@ virBhyveProbeCaps(unsigned int *caps) if ((ret = bhyveProbeCapsRTC_UTC(caps, binary))) goto out; + if ((ret = bhyveProbeCapsLPC_Bootrom(caps, binary))) + goto out; + out: VIR_FREE(binary); return ret; diff --git a/src/bhyve/bhyve_capabilities.h b/src/bhyve/bhyve_capabilities.h index 0eb22a4..5ea3294 100644 --- a/src/bhyve/bhyve_capabilities.h +++ b/src/bhyve/bhyve_capabilities.h @@ -33,6 +33,7 @@ typedef enum { typedef enum { BHYVE_CAP_RTC_UTC = 1, + BHYVE_CAP_LPC_BOOTROM = 2, } virBhyveCapsFlags; int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps); -- 2.7.0

--- src/bhyve/bhyve_command.c | 6 ++++++ src/bhyve/bhyve_driver.c | 27 +++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index 9ad3f9b..a504788 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -281,6 +281,12 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn, virCommandAddArg(cmd, "-P"); /* vmexit from guest on pause */ virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); + if (def->os.bootloader == NULL && + def->os.loader && + (bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM) != 0) { + virCommandAddArg(cmd, "-s"); + virCommandAddArgFormat(cmd, "0:1,bootrom,%s", def->os.loader->path); + } /* Devices */ for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c index 8036661..cd56a89 100644 --- a/src/bhyve/bhyve_driver.c +++ b/src/bhyve/bhyve_driver.c @@ -729,15 +729,34 @@ bhyveConnectDomainXMLToNative(virConnectPtr conn, if (bhyveDomainAssignAddresses(def, NULL) < 0) goto cleanup; - if (!(loadcmd = virBhyveProcessBuildLoadCmd(conn, def, "<device.map>", + if (def->os.bootloader == NULL && + def->os.loader) { + + if ((def->os.loader->readonly != VIR_TRISTATE_BOOL_YES) + || (def->os.loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only read-only pflash is supported.")); + goto cleanup; + } + + if ((bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM) == 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Installed bhyve binary does not support " + "bootrom")); + goto cleanup; + } + } else { + if (!(loadcmd = virBhyveProcessBuildLoadCmd(conn, def, "<device.map>", NULL))) - goto cleanup; + goto cleanup; + + virBufferAdd(&buf, virCommandToString(loadcmd), -1); + virBufferAddChar(&buf, '\n'); + } if (!(cmd = virBhyveProcessBuildBhyveCmd(conn, def, true))) goto cleanup; - virBufferAdd(&buf, virCommandToString(loadcmd), -1); - virBufferAddChar(&buf, '\n'); virBufferAdd(&buf, virCommandToString(cmd), -1); if (virBufferCheckError(&buf) < 0) -- 2.7.0

--- tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args | 9 +++++++++ .../bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs | 1 + tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml | 23 ++++++++++++++++++++++ tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args | 10 ++++++++++ tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs | 1 + tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml | 23 ++++++++++++++++++++++ tests/bhyvexml2argvtest.c | 13 ++++++++++-- 7 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args new file mode 100644 index 0000000..88de179 --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args @@ -0,0 +1,9 @@ +/usr/sbin/bhyve \ +-c 1 \ +-m 214 \ +-u \ +-H \ +-P \ +-s 0:0,hostbridge \ +-s 3:0,virtio-net,faketapdev,mac=52:54:00:00:00:00 \ +-s 2:0,ahci-hd,/tmp/freebsd.img bhyve diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs new file mode 100644 index 0000000..421376d --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs @@ -0,0 +1 @@ +dummy diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml new file mode 100644 index 0000000..eacae99 --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml @@ -0,0 +1,23 @@ +<domain type='bhyve'> + <name>bhyve</name> + <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid> + <memory>219136</memory> + <vcpu>1</vcpu> + <os> + <type>hvm</type> + <loader readonly="yes" type="pflash">test.fd</loader> + </os> + <devices> + <disk type='file'> + <driver name='file' type='raw'/> + <source file='/tmp/freebsd.img'/> + <target dev='hda' bus='sata'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </disk> + <interface type='bridge'> + <model type='virtio'/> + <source bridge="virbr0"/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + </devices> +</domain> diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args new file mode 100644 index 0000000..3f6ef65 --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args @@ -0,0 +1,10 @@ +/usr/sbin/bhyve \ +-c 1 \ +-m 214 \ +-u \ +-H \ +-P \ +-s 0:0,hostbridge \ +-s 0:1,bootrom,test.fd \ +-s 3:0,virtio-net,faketapdev,mac=52:54:00:00:00:00 \ +-s 2:0,ahci-hd,/tmp/freebsd.img bhyve diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs new file mode 100644 index 0000000..421376d --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs @@ -0,0 +1 @@ +dummy diff --git a/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml new file mode 100644 index 0000000..eacae99 --- /dev/null +++ b/tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml @@ -0,0 +1,23 @@ +<domain type='bhyve'> + <name>bhyve</name> + <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid> + <memory>219136</memory> + <vcpu>1</vcpu> + <os> + <type>hvm</type> + <loader readonly="yes" type="pflash">test.fd</loader> + </os> + <devices> + <disk type='file'> + <driver name='file' type='raw'/> + <source file='/tmp/freebsd.img'/> + <target dev='hda' bus='sata'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </disk> + <interface type='bridge'> + <model type='virtio'/> + <source bridge="virbr0"/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + </devices> +</domain> diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c index 7a2d366..5137251 100644 --- a/tests/bhyvexml2argvtest.c +++ b/tests/bhyvexml2argvtest.c @@ -44,9 +44,13 @@ static int testCompareXMLToArgvFiles(const char *xml, conn->privateData = &driver; cmd = virBhyveProcessBuildBhyveCmd(conn, vmdef, false); - ldcmd = virBhyveProcessBuildLoadCmd(conn, vmdef, "<device.map>", + if (!vmdef->os.loader) + ldcmd = virBhyveProcessBuildLoadCmd(conn, vmdef, "<device.map>", &actualdm); + if ((ldcmd == NULL) && (vmdef->os.loader)) + ldcmd = virCommandNew("dummy"); + if ((cmd == NULL) || (ldcmd == NULL)) { if (flags & FLAG_EXPECT_FAILURE) { ret = 0; @@ -151,7 +155,7 @@ mymain(void) DO_TEST_FULL(name, FLAG_EXPECT_PARSE_ERROR) driver.grubcaps = BHYVE_GRUB_CAP_CONSDEV; - driver.bhyvecaps = BHYVE_CAP_RTC_UTC; + driver.bhyvecaps = BHYVE_CAP_RTC_UTC | BHYVE_CAP_LPC_BOOTROM; DO_TEST("base"); DO_TEST("acpiapic"); @@ -179,6 +183,11 @@ mymain(void) DO_TEST("serial-grub-nocons"); + DO_TEST("uefi"); + + driver.bhyvecaps &= ~BHYVE_CAP_LPC_BOOTROM; + DO_TEST_FAILURE("nouefi"); + virObjectUnref(driver.caps); virObjectUnref(driver.xmlopt); -- 2.7.0
participants (1)
-
Fabian Freyer