From: "Richard W.M. Jones" <rjones(a)redhat.com>
If supermin-helper >= 4.1.5 is found, use the new-style syntax and if
the architecture requires it (only ARM for now) implement device
trees.
This means we pass a supermin-helper --dtb option to find the right
device tree (currently Versatile Express A9, since that's what we pass
to qemu in the -M option). This makes supermin-helper find a
compatible device tree file.
Also that we pass the corresponding dtb file to qemu via the qemu -dtb
option, or to libvirt via the <dtb> element.
---
configure.ac | 12 +++
src/appliance.c | 279 +++++++++++++++++++++++++++++++++++++++----------
src/guestfs-internal.h | 2 +-
src/launch-direct.c | 9 +-
src/launch-libvirt.c | 16 ++-
src/launch-uml.c | 5 +-
6 files changed, 257 insertions(+), 66 deletions(-)
diff --git a/configure.ac b/configure.ac
index cb0f191..4e194e8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -463,6 +463,18 @@ AC_MSG_RESULT([$supermin_helper_compressed_cpio])
AM_CONDITIONAL([SUPERMIN_HELPER_COMPRESSED_CPIO],
[test "x$supermin_helper_compressed_cpio" = "xyes"])
+dnl supermin >= 4.1.5 supports device trees and uses a new style command
+dnl syntax.
+AC_MSG_CHECKING([if supermin-helper supports device trees and new style command syntax])
+if test $supermin_helper_version_int -ge 4001005; then
+ supermin_helper_new_style_syntax=yes
+ AC_DEFINE([SUPERMIN_HELPER_NEW_STYLE_SYNTAX],[1],
+ [Define to 1 if you have supermin-helper >= 4.1.5.])
+else
+ supermin_helper_new_style_syntax=no
+fi
+AC_MSG_RESULT([$supermin_helper_new_style_syntax])
+
dnl Pass supermin --packager-config option.
dnl
dnl Note that in febootstrap >= 3.21 / supermin >= 4.1.0, this option
diff --git a/src/appliance.c b/src/appliance.c
index 7f8fb0a..2432e51 100644
--- a/src/appliance.c
+++ b/src/appliance.c
@@ -41,11 +41,16 @@
#include "guestfs-internal-actions.h"
#include "guestfs_protocol.h"
+/* Architectures that use device trees. */
+#ifdef __arm__
+#define ARCH_HAS_DEVICE_TREE 1
+#endif
+
/* Old-style appliance is going to be obsoleted. */
static const char *kernel_name = "vmlinuz." host_cpu;
static const char *initrd_name = "initramfs." host_cpu ".img";
-static int build_appliance (guestfs_h *g, char **kernel, char **initrd, char
**appliance);
+static int build_appliance (guestfs_h *g, char **kernel, char **dtb, char **initrd, char
**appliance);
static int find_path (guestfs_h *g, int (*pred) (guestfs_h *g, const char *pelem, void
*data), void *data, char **pelem);
static int dir_contains_file (const char *dir, const char *file);
static int dir_contains_files (const char *dir, ...);
@@ -53,9 +58,9 @@ static int contains_old_style_appliance (guestfs_h *g, const char *path,
void *d
static int contains_fixed_appliance (guestfs_h *g, const char *path, void *data);
static int contains_supermin_appliance (guestfs_h *g, const char *path, void *data);
static char *calculate_supermin_checksum (guestfs_h *g, const char *supermin_path);
-static int check_for_cached_appliance (guestfs_h *g, const char *supermin_path, const
char *checksum, uid_t uid, char **kernel, char **initrd, char **appliance);
-static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, const char
*checksum, uid_t uid, char **kernel, char **initrd, char **appliance);
-static int hard_link_to_cached_appliance (guestfs_h *g, const char *cachedir, char
**kernel, char **initrd, char **appliance);
+static int check_for_cached_appliance (guestfs_h *g, const char *supermin_path, const
char *checksum, uid_t uid, char **kernel, char **dtb, char **initrd, char **appliance);
+static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, const char
*checksum, uid_t uid, char **kernel, char **dtb, char **initrd, char **appliance);
+static int hard_link_to_cached_appliance (guestfs_h *g, const char *cachedir, char
**kernel, char **dtb, char **initrd, char **appliance);
static int run_supermin_helper (guestfs_h *g, const char *supermin_path, const char
*cachedir);
/* RHBZ#790721: It makes no sense to have multiple threads racing to
@@ -101,10 +106,11 @@ gl_lock_define_initialized (static, building_lock);
* If one is found, return it.
*
* The supermin appliance cache directory lives in
- * $TMPDIR/.guestfs-$UID/ and consists of four files:
+ * $TMPDIR/.guestfs-$UID/ and consists of up to five files:
*
* $TMPDIR/.guestfs-$UID/checksum - the checksum
* $TMPDIR/.guestfs-$UID/kernel - the kernel
+ * $TMPDIR/.guestfs-$UID/dtb - the device tree (on ARM)
* $TMPDIR/.guestfs-$UID/initrd - the supermin initrd
* $TMPDIR/.guestfs-$UID/root - the appliance
*
@@ -118,6 +124,7 @@ gl_lock_define_initialized (static, building_lock);
* appliance afterwards:
*
* $TMPDIR/.guestfs-$UID/kernel.$PID
+ * $TMPDIR/.guestfs-$UID/dtb.$PID
* $TMPDIR/.guestfs-$UID/initrd.$PID
* $TMPDIR/.guestfs-$UID/root.$PID
*
@@ -139,14 +146,15 @@ gl_lock_define_initialized (static, building_lock);
int
guestfs___build_appliance (guestfs_h *g,
char **kernel_rtn,
+ char **dtb_rtn,
char **initrd_rtn,
char **appliance_rtn)
{
int r;
- char *kernel, *initrd, *appliance;
+ char *kernel, *dtb, *initrd, *appliance;
gl_lock_lock (building_lock);
- r = build_appliance (g, &kernel, &initrd, &appliance);
+ r = build_appliance (g, &kernel, &dtb, &initrd, &appliance);
gl_lock_unlock (building_lock);
if (r == -1)
@@ -156,6 +164,7 @@ guestfs___build_appliance (guestfs_h *g,
* the caller double-freeing (RHBZ#983218).
*/
*kernel_rtn = kernel;
+ *dtb_rtn = dtb;
*initrd_rtn = initrd;
*appliance_rtn = appliance;
return 0;
@@ -164,6 +173,7 @@ guestfs___build_appliance (guestfs_h *g,
static int
build_appliance (guestfs_h *g,
char **kernel,
+ char **dtb,
char **initrd,
char **appliance)
{
@@ -184,13 +194,13 @@ build_appliance (guestfs_h *g,
if (checksum) {
/* Step (3): cached appliance exists? */
r = check_for_cached_appliance (g, supermin_path, checksum, uid,
- kernel, initrd, appliance);
+ kernel, dtb, initrd, appliance);
if (r != 0)
return r == 1 ? 0 : -1;
/* Step (4): build supermin appliance. */
return build_supermin_appliance (g, supermin_path, checksum, uid,
- kernel, initrd, appliance);
+ kernel, dtb, initrd, appliance);
}
}
@@ -207,6 +217,14 @@ build_appliance (guestfs_h *g,
sprintf (*kernel, "%s/kernel", path);
sprintf (*initrd, "%s/initrd", path);
sprintf (*appliance, "%s/root", path);
+
+ /* The dtb file may or may not exist in the fixed appliance. */
+ if (dir_contains_file (path, "dtb")) {
+ *dtb = safe_malloc (g, len + 3 /* "dtb" */ + 2);
+ sprintf (*dtb, "%s/dtb", path);
+ }
+ else
+ *dtb = NULL;
return 0;
}
@@ -218,6 +236,7 @@ build_appliance (guestfs_h *g,
if (r == 1) {
size_t len = strlen (path);
*kernel = safe_malloc (g, len + strlen (kernel_name) + 2);
+ *dtb = NULL;
*initrd = safe_malloc (g, len + strlen (initrd_name) + 2);
sprintf (*kernel, "%s/%s", path, kernel_name);
sprintf (*initrd, "%s/%s", path, initrd_name);
@@ -262,48 +281,6 @@ read_checksum (guestfs_h *g, void *checksumv, const char *line,
size_t len)
strcpy (checksum, line);
}
-/* supermin_path is a path which is known to contain a supermin
- * appliance. Using supermin-helper -f checksum calculate
- * the checksum so we can see if it is cached.
- */
-static char *
-calculate_supermin_checksum (guestfs_h *g, const char *supermin_path)
-{
- size_t len;
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
- int pass_u_g_args = getuid () != geteuid () || getgid () != getegid ();
- char checksum[MAX_CHECKSUM_LEN + 1] = { 0 };
-
- guestfs___cmd_add_arg (cmd, SUPERMIN_HELPER);
- if (g->verbose)
- guestfs___cmd_add_arg (cmd, "--verbose");
- if (pass_u_g_args) {
- guestfs___cmd_add_arg (cmd, "-u");
- guestfs___cmd_add_arg_format (cmd, "%d", geteuid ());
- guestfs___cmd_add_arg (cmd, "-g");
- guestfs___cmd_add_arg_format (cmd, "%d", getegid ());
- }
- guestfs___cmd_add_arg (cmd, "-f");
- guestfs___cmd_add_arg (cmd, "checksum");
- guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
- guestfs___cmd_add_arg (cmd, host_cpu);
- guestfs___cmd_set_stdout_callback (cmd, read_checksum, checksum, 0);
-
- /* Errors here are non-fatal, so we don't need to call error(). */
- if (guestfs___cmd_run (cmd) == -1)
- return NULL;
-
- debug (g, "checksum of existing appliance: %s", checksum);
-
- len = strlen (checksum);
- if (len < 16) { /* sanity check */
- warning (g, "supermin-helper -f checksum returned a short string");
- return NULL;
- }
-
- return safe_strndup (g, checksum, len);
-}
-
static int
process_exists (int pid)
{
@@ -317,8 +294,8 @@ process_exists (int pid)
}
/* Garbage collect appliance hard links. Files that match
- * (kernel|initrd|root).$PID where the corresponding PID doesn't exist
- * are deleted. Note that errors in this function don't matter.
+ * (kernel|dtb|initrd|root).$PID where the corresponding PID doesn't
+ * exist are deleted. Note that errors in this function don't matter.
* There may also be other libguestfs processes racing to do the same
* thing here.
*/
@@ -337,6 +314,9 @@ garbage_collect_appliances (const char *cachedir)
if (sscanf (d->d_name, "kernel.%d", &pid) == 1 &&
process_exists (pid) == 0)
unlinkat (dirfd (dir), d->d_name, 0);
+ else if (sscanf (d->d_name, "dtb.%d", &pid) == 1 &&
+ process_exists (pid) == 0)
+ unlinkat (dirfd (dir), d->d_name, 0);
else if (sscanf (d->d_name, "initrd.%d", &pid) == 1 &&
process_exists (pid) == 0)
unlinkat (dirfd (dir), d->d_name, 0);
@@ -352,7 +332,8 @@ static int
check_for_cached_appliance (guestfs_h *g,
const char *supermin_path, const char *checksum,
uid_t uid,
- char **kernel, char **initrd, char **appliance)
+ char **kernel, char **dtb,
+ char **initrd, char **appliance)
{
CLEANUP_FREE char *tmpdir = guestfs_get_cachedir (g);
@@ -440,7 +421,7 @@ check_for_cached_appliance (guestfs_h *g,
* a read lock on the checksum file. Make hard links to the files.
*/
if (hard_link_to_cached_appliance (g, cachedir,
- kernel, initrd, appliance) == -1) {
+ kernel, dtb, initrd, appliance) == -1) {
close (fd);
return -1;
}
@@ -452,6 +433,7 @@ check_for_cached_appliance (guestfs_h *g,
* freed along this error path.
*/
free (*kernel);
+ free (*dtb);
free (*initrd);
free (*appliance);
return -1;
@@ -471,7 +453,8 @@ static int
build_supermin_appliance (guestfs_h *g,
const char *supermin_path, const char *checksum,
uid_t uid,
- char **kernel, char **initrd, char **appliance)
+ char **kernel, char **dtb,
+ char **initrd, char **appliance)
{
CLEANUP_FREE char *tmpdir = guestfs_get_cachedir (g);
size_t len;
@@ -571,6 +554,18 @@ build_supermin_appliance (guestfs_h *g,
return -1;
}
+#if ARCH_HAS_DEVICE_TREE
+ snprintf (filename, len, "%s/dtb", tmpcd);
+ snprintf (filename2, len, "%s/dtb", cachedir);
+ unlink (filename2);
+ if (rename (filename, filename2) == -1) {
+ perrorf (g, "rename: %s %s", filename, filename2);
+ close (fd);
+ guestfs___recursive_remove_dir (g, tmpcd);
+ return -1;
+ }
+#endif
+
snprintf (filename, len, "%s/initrd", tmpcd);
snprintf (filename2, len, "%s/initrd", cachedir);
unlink (filename2);
@@ -595,7 +590,7 @@ build_supermin_appliance (guestfs_h *g,
/* Now finish off by linking to the cached appliance and returning it. */
if (hard_link_to_cached_appliance (g, cachedir,
- kernel, initrd, appliance) == -1) {
+ kernel, dtb, initrd, appliance) == -1) {
close (fd);
return -1;
}
@@ -607,6 +602,7 @@ build_supermin_appliance (guestfs_h *g,
* freed along this error path.
*/
free (*kernel);
+ free (*dtb);
free (*initrd);
free (*appliance);
return -1;
@@ -619,15 +615,18 @@ build_supermin_appliance (guestfs_h *g,
static int
hard_link_to_cached_appliance (guestfs_h *g,
const char *cachedir,
- char **kernel, char **initrd, char **appliance)
+ char **kernel, char **dtb,
+ char **initrd, char **appliance)
{
pid_t pid = getpid ();
size_t len = strlen (cachedir) + 32;
*kernel = safe_malloc (g, len);
+ *dtb = safe_malloc (g, len);
*initrd = safe_malloc (g, len);
*appliance = safe_malloc (g, len);
snprintf (*kernel, len, "%s/kernel.%d", cachedir, pid);
+ snprintf (*dtb, len, "%s/dtb.%d", cachedir, pid);
snprintf (*initrd, len, "%s/initrd.%d", cachedir, pid);
snprintf (*appliance, len, "%s/root.%d", cachedir, pid);
@@ -640,6 +639,20 @@ hard_link_to_cached_appliance (guestfs_h *g,
}
(void) utimes (filename, NULL);
+ snprintf (filename, len, "%s/dtb", cachedir);
+ (void) unlink (*dtb);
+ if (link (filename, *dtb) == -1) {
+ if (errno == ENOENT) {
+ /* dtb doesn't exist -- this is OK */
+ free (*dtb);
+ *dtb = NULL;
+ } else {
+ perrorf (g, "link: %s %s", filename, *kernel);
+ goto error;
+ }
+ }
+ (void) utimes (filename, NULL);
+
snprintf (filename, len, "%s/initrd", cachedir);
(void) unlink (*initrd);
if (link (filename, *initrd) == -1) {
@@ -673,6 +686,7 @@ hard_link_to_cached_appliance (guestfs_h *g,
error:
free (*kernel);
+ free (*dtb);
free (*initrd);
free (*appliance);
return -1;
@@ -681,6 +695,153 @@ hard_link_to_cached_appliance (guestfs_h *g,
/* Run supermin-helper and tell it to generate the
* appliance.
*/
+
+#ifdef SUPERMIN_HELPER_NEW_STYLE_SYNTAX
+
+/* supermin_path is a path which is known to contain a supermin
+ * appliance. Using supermin-helper -f checksum calculate
+ * the checksum so we can see if it is cached.
+ */
+static char *
+calculate_supermin_checksum (guestfs_h *g, const char *supermin_path)
+{
+ size_t len;
+ CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
+ int pass_u_g_args = getuid () != geteuid () || getgid () != getegid ();
+ char checksum[MAX_CHECKSUM_LEN + 1] = { 0 };
+
+ guestfs___cmd_add_arg (cmd, SUPERMIN_HELPER);
+ if (g->verbose)
+ guestfs___cmd_add_arg (cmd, "--verbose");
+ if (pass_u_g_args) {
+ guestfs___cmd_add_arg (cmd, "-u");
+ guestfs___cmd_add_arg_format (cmd, "%d", geteuid ());
+ guestfs___cmd_add_arg (cmd, "-g");
+ guestfs___cmd_add_arg_format (cmd, "%d", getegid ());
+ }
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "checksum");
+ guestfs___cmd_add_arg (cmd, "--host-cpu");
+ guestfs___cmd_add_arg (cmd, host_cpu);
+ guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
+ guestfs___cmd_set_stdout_callback (cmd, read_checksum, checksum, 0);
+
+ /* Errors here are non-fatal, so we don't need to call error(). */
+ if (guestfs___cmd_run (cmd) == -1)
+ return NULL;
+
+ debug (g, "checksum of existing appliance: %s", checksum);
+
+ len = strlen (checksum);
+ if (len < 16) { /* sanity check */
+ warning (g, "supermin-helper -f checksum returned a short string");
+ return NULL;
+ }
+
+ return safe_strndup (g, checksum, len);
+}
+
+static int
+run_supermin_helper (guestfs_h *g, const char *supermin_path,
+ const char *cachedir)
+{
+ CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
+ int r;
+ uid_t uid = getuid ();
+ uid_t euid = geteuid ();
+ gid_t gid = getgid ();
+ gid_t egid = getegid ();
+ int pass_u_g_args = uid != euid || gid != egid;
+
+ guestfs___cmd_add_arg (cmd, SUPERMIN_HELPER);
+ if (g->verbose)
+ guestfs___cmd_add_arg (cmd, "--verbose");
+ if (pass_u_g_args) {
+ guestfs___cmd_add_arg (cmd, "-u");
+ guestfs___cmd_add_arg_format (cmd, "%d", euid);
+ guestfs___cmd_add_arg (cmd, "-g");
+ guestfs___cmd_add_arg_format (cmd, "%d", egid);
+ }
+ guestfs___cmd_add_arg (cmd, "--copy-kernel");
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "ext2");
+ guestfs___cmd_add_arg (cmd, "--host-cpu");
+ guestfs___cmd_add_arg (cmd, host_cpu);
+#if ARCH_HAS_DEVICE_TREE
+ guestfs___cmd_add_arg (cmd, "--dtb");
+ guestfs___cmd_add_arg (cmd, "vexpress*a9.dtb");
+#endif
+ guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
+ guestfs___cmd_add_arg (cmd, "--output-kernel");
+ guestfs___cmd_add_arg_format (cmd, "%s/kernel", cachedir);
+#if ARCH_HAS_DEVICE_TREE
+ guestfs___cmd_add_arg (cmd, "--output-dtb");
+ guestfs___cmd_add_arg_format (cmd, "%s/dtb", cachedir);
+#endif
+ guestfs___cmd_add_arg (cmd, "--output-initrd");
+ guestfs___cmd_add_arg_format (cmd, "%s/initrd", cachedir);
+ guestfs___cmd_add_arg (cmd, "--output-appliance");
+ guestfs___cmd_add_arg_format (cmd, "%s/root", cachedir);
+
+ r = guestfs___cmd_run (cmd);
+ if (r == -1)
+ return -1;
+ if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
+ guestfs___external_command_failed (g, r, SUPERMIN_HELPER, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* ! SUPERMIN_HELPER_NEW_STYLE_SYNTAX */
+
+#if ARCH_HAS_DEVICE_TREE
+#error "This architecture has device trees, so requires supermin-helper >=
4.1.5"
+#endif
+
+/* supermin_path is a path which is known to contain a supermin
+ * appliance. Using supermin-helper -f checksum calculate
+ * the checksum so we can see if it is cached.
+ */
+static char *
+calculate_supermin_checksum (guestfs_h *g, const char *supermin_path)
+{
+ size_t len;
+ CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g);
+ int pass_u_g_args = getuid () != geteuid () || getgid () != getegid ();
+ char checksum[MAX_CHECKSUM_LEN + 1] = { 0 };
+
+ guestfs___cmd_add_arg (cmd, SUPERMIN_HELPER);
+ if (g->verbose)
+ guestfs___cmd_add_arg (cmd, "--verbose");
+ if (pass_u_g_args) {
+ guestfs___cmd_add_arg (cmd, "-u");
+ guestfs___cmd_add_arg_format (cmd, "%d", geteuid ());
+ guestfs___cmd_add_arg (cmd, "-g");
+ guestfs___cmd_add_arg_format (cmd, "%d", getegid ());
+ }
+ guestfs___cmd_add_arg (cmd, "-f");
+ guestfs___cmd_add_arg (cmd, "checksum");
+ guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path);
+ guestfs___cmd_add_arg (cmd, host_cpu);
+ guestfs___cmd_set_stdout_callback (cmd, read_checksum, checksum, 0);
+
+ /* Errors here are non-fatal, so we don't need to call error(). */
+ if (guestfs___cmd_run (cmd) == -1)
+ return NULL;
+
+ debug (g, "checksum of existing appliance: %s", checksum);
+
+ len = strlen (checksum);
+ if (len < 16) { /* sanity check */
+ warning (g, "supermin-helper -f checksum returned a short string");
+ return NULL;
+ }
+
+ return safe_strndup (g, checksum, len);
+}
+
static int
run_supermin_helper (guestfs_h *g, const char *supermin_path,
const char *cachedir)
@@ -722,6 +883,8 @@ run_supermin_helper (guestfs_h *g, const char *supermin_path,
return 0;
}
+#endif /* ! SUPERMIN_HELPER_NEW_STYLE_SYNTAX */
+
/* Search elements of g->path, returning the first path element which
* matches the predicate function 'pred'.
*
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 84b4d57..8a17da6 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -631,7 +631,7 @@ extern char *guestfs___drive_source_qemu_param (guestfs_h *g, const
struct drive
extern void guestfs___free_drive_source (struct drive_source *src);
/* appliance.c */
-extern int guestfs___build_appliance (guestfs_h *g, char **kernel, char **initrd, char
**appliance);
+extern int guestfs___build_appliance (guestfs_h *g, char **kernel, char **dtb, char
**initrd, char **appliance);
/* launch.c */
extern int64_t guestfs___timeval_diff (const struct timeval *x, const struct timeval
*y);
diff --git a/src/launch-direct.c b/src/launch-direct.c
index d704069..ef261b5 100644
--- a/src/launch-direct.c
+++ b/src/launch-direct.c
@@ -180,7 +180,8 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
int sv[2];
char guestfsd_sock[256];
struct sockaddr_un addr;
- CLEANUP_FREE char *kernel = NULL, *initrd = NULL, *appliance = NULL;
+ CLEANUP_FREE char *kernel = NULL, *dtb = NULL,
+ *initrd = NULL, *appliance = NULL;
int has_appliance_drive;
CLEANUP_FREE char *appliance_dev = NULL;
uint32_t size;
@@ -204,7 +205,7 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
TRACE0 (launch_build_appliance_start);
/* Locate and/or build the appliance. */
- if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1)
+ if (guestfs___build_appliance (g, &kernel, &dtb, &initrd, &appliance)
== -1)
return -1;
has_appliance_drive = appliance != NULL;
@@ -369,6 +370,10 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
ADD_CMDLINE ("-kernel");
ADD_CMDLINE (kernel);
+ if (dtb) {
+ ADD_CMDLINE ("-dtb");
+ ADD_CMDLINE (dtb);
+ }
ADD_CMDLINE ("-initrd");
ADD_CMDLINE (initrd);
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index b3e729f..afb45f0 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -122,7 +122,8 @@ struct drive_libvirt {
*/
struct libvirt_xml_params {
struct backend_libvirt_data *data;
- char *kernel; /* paths to kernel and initrd */
+ char *kernel; /* paths to kernel, dtb and initrd */
+ char *dtb;
char *initrd;
char *appliance_overlay; /* path to qcow2 overlay backed by appliance */
char appliance_dev[64]; /* appliance device name */
@@ -164,6 +165,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
struct libvirt_xml_params params = {
.data = data,
.kernel = NULL,
+ .dtb = NULL,
.initrd = NULL,
.appliance_overlay = NULL,
};
@@ -240,8 +242,8 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
if (g->verbose)
guestfs___print_timestamped_message (g, "build appliance");
- if (guestfs___build_appliance (g, ¶ms.kernel, ¶ms.initrd,
- &appliance) == -1)
+ if (guestfs___build_appliance (g, ¶ms.kernel, ¶ms.dtb,
+ ¶ms.initrd, &appliance) == -1)
goto cleanup;
guestfs___launch_send_progress (g, 3);
@@ -472,6 +474,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
data->dom = dom;
free (params.kernel);
+ free (params.dtb);
free (params.initrd);
free (params.appliance_overlay);
@@ -497,6 +500,7 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
virConnectClose (conn);
free (params.kernel);
+ free (params.dtb);
free (params.initrd);
free (params.appliance_overlay);
@@ -894,6 +898,12 @@ construct_libvirt_xml_boot (guestfs_h *g,
XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST params->kernel));
XMLERROR (-1, xmlTextWriterEndElement (xo));
+ if (params->dtb) {
+ XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "dtb"));
+ XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST params->dtb));
+ XMLERROR (-1, xmlTextWriterEndElement (xo));
+ }
+
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "initrd"));
XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST params->initrd));
XMLERROR (-1, xmlTextWriterEndElement (xo));
diff --git a/src/launch-uml.c b/src/launch-uml.c
index 4ae4568..936afc6 100644
--- a/src/launch-uml.c
+++ b/src/launch-uml.c
@@ -102,7 +102,8 @@ launch_uml (guestfs_h *g, void *datav, const char *arg)
int console_sock = -1, daemon_sock = -1;
int r;
int csv[2], dsv[2];
- CLEANUP_FREE char *kernel = NULL, *initrd = NULL, *appliance = NULL;
+ CLEANUP_FREE char *kernel = NULL, *dtb = NULL,
+ *initrd = NULL, *appliance = NULL;
int has_appliance_drive;
CLEANUP_FREE char *appliance_cow = NULL;
uint32_t size;
@@ -127,7 +128,7 @@ launch_uml (guestfs_h *g, void *datav, const char *arg)
}
/* Locate and/or build the appliance. */
- if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1)
+ if (guestfs___build_appliance (g, &kernel, &dtb, &initrd, &appliance)
== -1)
return -1;
has_appliance_drive = appliance != NULL;
--
1.8.3.1