libdfu: Add a merge command to dfu-tool

This commit is contained in:
Richard Hughes 2015-11-15 19:00:03 +00:00
parent 31aa1dd3df
commit 3a40e94567

View File

@ -503,6 +503,120 @@ dfu_tool_set_alt_setting_name (DfuToolPrivate *priv, gchar **values, GError **er
return dfu_firmware_write_file (firmware, file, NULL, error);
}
/**
* dfu_tool_merge:
**/
static gboolean
dfu_tool_merge (DfuToolPrivate *priv, gchar **values, GError **error)
{
guint16 pid = 0xffff;
guint16 rel = 0xffff;
guint16 vid = 0xffff;
guint i;
g_autofree gchar *str_debug = NULL;
g_autoptr(DfuFirmware) firmware = NULL;
g_autoptr(GFile) file = NULL;
/* check args */
if (g_strv_length (values) < 3) {
g_set_error_literal (error,
DFU_ERROR,
DFU_ERROR_INTERNAL,
"Invalid arguments, expected "
"FILE-OUT FILE1 FILE2 [FILE3...]"
" -- e.g. `combined.dfu lib.dfu app.dfu`");
return FALSE;
}
/* parse source files */
firmware = dfu_firmware_new ();
dfu_firmware_set_format (firmware, DFU_FIRMWARE_FORMAT_DFUSE);
for (i = 1; values[i] != NULL; i++) {
GPtrArray *images;
guint j;
g_autoptr(GFile) file_tmp = NULL;
g_autoptr(DfuFirmware) firmware_tmp = NULL;
/* open up source */
file_tmp = g_file_new_for_path (values[i]);
firmware_tmp = dfu_firmware_new ();
if (!dfu_firmware_parse_file (firmware_tmp, file_tmp,
DFU_FIRMWARE_PARSE_FLAG_NONE,
NULL, error)) {
return FALSE;
}
/* check same vid:pid:rel */
if (vid != 0xffff &&
dfu_firmware_get_vid (firmware_tmp) != vid) {
g_set_error (error,
DFU_ERROR,
DFU_ERROR_INVALID_FILE,
"Vendor ID was already set as "
"0x%04x, %s is 0x%04x",
vid, values[i],
dfu_firmware_get_vid (firmware_tmp));
return FALSE;
}
if (pid != 0xffff &&
dfu_firmware_get_pid (firmware_tmp) != pid) {
g_set_error (error,
DFU_ERROR,
DFU_ERROR_INVALID_FILE,
"Product ID was already set as "
"0x%04x, %s is 0x%04x",
pid, values[i],
dfu_firmware_get_pid (firmware_tmp));
return FALSE;
}
if (rel != 0xffff &&
dfu_firmware_get_release (firmware_tmp) != rel) {
g_set_error (error,
DFU_ERROR,
DFU_ERROR_INVALID_FILE,
"Release was already set as "
"0x%04x, %s is 0x%04x",
rel, values[i],
dfu_firmware_get_release (firmware_tmp));
return FALSE;
}
/* add all images to destination */
images = dfu_firmware_get_images (firmware_tmp);
for (j = 0; j < images->len; j++) {
DfuImage *image;
guint alt_id;
/* verify the alt-setting does not already exist */
image = g_ptr_array_index (images, j);
alt_id = dfu_image_get_alt_setting (image);
g_print ("Adding alternative setting ID of 0x%02x\n",
alt_id);
if (dfu_firmware_get_image (firmware, alt_id) != NULL) {
g_print ("WARNING: The alternative setting "
"ID of 0x%02x has already been added\n",
alt_id);
}
/* add to destination */
dfu_firmware_add_image (firmware, image);
}
/* save last IDs */
vid = dfu_firmware_get_vid (firmware_tmp);
pid = dfu_firmware_get_pid (firmware_tmp);
rel = dfu_firmware_get_release (firmware_tmp);
}
/* print the new object */
str_debug = dfu_firmware_to_string (firmware);
g_print ("New merged file:\n%s\n", str_debug);
/* write out new file */
file = g_file_new_for_path (values[0]);
return dfu_firmware_write_file (firmware, file, NULL, error);
}
/**
* dfu_tool_convert:
**/
@ -1105,6 +1219,12 @@ main (int argc, char *argv[])
/* TRANSLATORS: command description */
_("Convert firmware to DFU format"),
dfu_tool_convert);
dfu_tool_add (priv->cmd_array,
"merge",
NULL,
/* TRANSLATORS: command description */
_("Merge multiple firmware files into one"),
dfu_tool_merge);
dfu_tool_add (priv->cmd_array,
"set-vendor",
NULL,