[libvirt] [PATCH 2/6] bhyve: add support for booting from UEFI

Roman Bogorodskiy bogorodskiy at gmail.com
Sun Feb 12 15:12:30 UTC 2017


From: Fabian Freyer <fabian.freyer at physik.tu-berlin.de>

Allow to boot using UEFI rather than using an external boot loader
such as bhyveload or grub-bhyve.

Also, make LPC PCI-ISA bridge handling more flexible as now it's
needed not only for serial ports, but for bootrom as well.

Signed-off-by: Roman Bogorodskiy <bogorodskiy at gmail.com>
---
 src/bhyve/bhyve_command.c | 30 +++++++++++++++++++++++++-
 src/bhyve/bhyve_driver.c  | 27 +++++++++++++++++++----
 src/bhyve/bhyve_process.c | 55 +++++++++++++++++++++++++----------------------
 3 files changed, 81 insertions(+), 31 deletions(-)

diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
index e7131625c..450800920 100644
--- a/src/bhyve/bhyve_command.c
+++ b/src/bhyve/bhyve_command.c
@@ -163,7 +163,6 @@ bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd)
         return -1;
     }
 
-    virCommandAddArgList(cmd, "-s", "1,lpc", NULL);
     virCommandAddArg(cmd, "-l");
     virCommandAddArgFormat(cmd, "com%d,%s",
                            chr->target.port + 1, chr->source->data.file.path);
@@ -283,6 +282,14 @@ bhyveBuildVirtIODiskArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int
+bhyveBuildLPCArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
+                    virCommandPtr cmd)
+{
+    virCommandAddArgList(cmd, "-s", "1,lpc", NULL);
+    return 0;
+}
+
 virCommandPtr
 virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
                              virDomainDefPtr def, bool dryRun)
@@ -296,6 +303,7 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
      *            vm0
      */
     size_t i;
+    bool add_lpc = false;
 
     virCommandPtr cmd = virCommandNew(BHYVE);
 
@@ -350,6 +358,21 @@ 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) {
+        if ((bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM)) {
+            virCommandAddArg(cmd, "-l");
+            virCommandAddArgFormat(cmd, "bootrom,%s", def->os.loader->path);
+            add_lpc = true;
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Installed bhyve binary does not support "
+                             "UEFI loader"));
+            goto error;
+        }
+    }
+
     /* Devices */
     for (i = 0; i < def->ncontrollers; i++) {
         virDomainControllerDefPtr controller = def->controllers[i];
@@ -389,8 +412,13 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
             goto error;
         }
     }
+
+    if (add_lpc || def->nserials)
+        bhyveBuildLPCArgStr(def, cmd);
+
     if (bhyveBuildConsoleArgStr(def, cmd) < 0)
         goto error;
+
     virCommandAddArg(cmd, def->name);
 
     return cmd;
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index f4ccef32b..0f9961ae0 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -734,15 +734,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)
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 9d8097676..a97e300ff 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -165,38 +165,41 @@ virBhyveProcessStart(virConnectPtr conn,
     virCommandSetPidFile(cmd, privconn->pidfile);
     virCommandDaemonize(cmd);
 
-    /* Now bhyve command is constructed, meaning the
-     * domain is ready to be started, so we can build
-     * and execute bhyveload command */
-    rc = virBhyveFormatDevMapFile(vm->def->name, &devmap_file);
-    if (rc < 0)
-        goto cleanup;
+    if (vm->def->os.loader == NULL) {
+        /* Now bhyve command is constructed, meaning the
+         * domain is ready to be started, so we can build
+         * and execute bhyveload command */
 
-    if (!(load_cmd = virBhyveProcessBuildLoadCmd(conn, vm->def, devmap_file,
-                                                 &devicemap)))
-        goto cleanup;
-    virCommandSetOutputFD(load_cmd, &logfd);
-    virCommandSetErrorFD(load_cmd, &logfd);
+        rc = virBhyveFormatDevMapFile(vm->def->name, &devmap_file);
+        if (rc < 0)
+            goto cleanup;
 
-    if (devicemap != NULL) {
-        rc = virFileWriteStr(devmap_file, devicemap, 0644);
-        if (rc) {
-            virReportSystemError(errno,
-                                 _("Cannot write device.map '%s'"),
-                                 devmap_file);
+        if (!(load_cmd = virBhyveProcessBuildLoadCmd(conn, vm->def, devmap_file,
+                                                     &devicemap)))
             goto cleanup;
+        virCommandSetOutputFD(load_cmd, &logfd);
+        virCommandSetErrorFD(load_cmd, &logfd);
+
+        if (devicemap != NULL) {
+            rc = virFileWriteStr(devmap_file, devicemap, 0644);
+            if (rc) {
+                virReportSystemError(errno,
+                                     _("Cannot write device.map '%s'"),
+                                     devmap_file);
+                goto cleanup;
+            }
         }
-    }
 
-    /* Log generated command line */
-    virCommandWriteArgLog(load_cmd, logfd);
-    if ((pos = lseek(logfd, 0, SEEK_END)) < 0)
-        VIR_WARN("Unable to seek to end of logfile: %s",
-                 virStrerror(errno, ebuf, sizeof(ebuf)));
+        /* Log generated command line */
+        virCommandWriteArgLog(load_cmd, logfd);
+        if ((pos = lseek(logfd, 0, SEEK_END)) < 0)
+            VIR_WARN("Unable to seek to end of logfile: %s",
+                     virStrerror(errno, ebuf, sizeof(ebuf)));
 
-    VIR_DEBUG("Loading domain '%s'", vm->def->name);
-    if (virCommandRun(load_cmd, NULL) < 0)
-        goto cleanup;
+        VIR_DEBUG("Loading domain '%s'", vm->def->name);
+        if (virCommandRun(load_cmd, NULL) < 0)
+            goto cleanup;
+    }
 
     /* Now we can start the domain */
     VIR_DEBUG("Starting domain '%s'", vm->def->name);
-- 
2.11.0




More information about the libvir-list mailing list