Richard W.M. Jones
2013-Sep-06 17:47 UTC
[Libguestfs] [PATCH] arm: appliance: Add support for device trees (dtb's).
This is the libguestfs companion patch to: https://www.redhat.com/archives/libguestfs/2013-September/msg00045.html Rich.
Richard W.M. Jones
2013-Sep-06 17:47 UTC
[Libguestfs] [PATCH] arm: appliance: Add support for device trees (dtb's).
From: "Richard W.M. Jones" <rjones@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