From bca63edccf98f32e20ff149bb447ccef8b642458 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 9 Mar 2020 20:20:03 +0000 Subject: [PATCH] Add 'firmware-convert' subcommand to fwupdtool This is a useful function that allows us to use all the fwupdplugin loaders. --- data/bash-completion/fwupdtool.in | 18 ++++++ src/fu-tool.c | 96 +++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/data/bash-completion/fwupdtool.in b/data/bash-completion/fwupdtool.in index 1af67d5f7..0c9d850e3 100644 --- a/data/bash-completion/fwupdtool.in +++ b/data/bash-completion/fwupdtool.in @@ -1,6 +1,7 @@ _fwupdtool_cmd_list=( 'activate' 'build-firmware' + 'firmware-convert' 'firmware-parse' 'get-updates' 'get-upgrades' @@ -135,6 +136,23 @@ _fwupdtool() _show_modifiers fi ;; + firmware-convert) + #file in + if [[ "$prev" = "$command" ]]; then + _filedir + #file out + elif [[ "$prev" = "${COMP_WORDS[2]}" ]]; then + _filedir + #firmware_type in + elif [[ "$prev" = "${COMP_WORDS[3]}" ]]; then + _show_firmware_types + #firmware_type out + elif [[ "$prev" = "${COMP_WORDS[4]}" ]]; then + _show_firmware_types + else + _show_modifiers + fi + ;; *) #find first command if [[ ${COMP_CWORD} = 1 ]]; then diff --git a/src/fu-tool.c b/src/fu-tool.c index b07a2192c..b5d95ae89 100644 --- a/src/fu-tool.c +++ b/src/fu-tool.c @@ -1546,6 +1546,96 @@ fu_util_firmware_parse (FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } +static gboolean +fu_util_firmware_convert (FuUtilPrivate *priv, gchar **values, GError **error) +{ + GType gtype_dst; + GType gtype_src; + g_autofree gchar *firmware_type_dst = NULL; + g_autofree gchar *firmware_type_src = NULL; + g_autofree gchar *str_dst = NULL; + g_autofree gchar *str_src = NULL; + g_autoptr(FuFirmware) firmware_dst = NULL; + g_autoptr(FuFirmware) firmware_src = NULL; + g_autoptr(GBytes) blob_dst = NULL; + g_autoptr(GBytes) blob_src = NULL; + g_autoptr(GPtrArray) images = NULL; + + /* check args */ + if (g_strv_length (values) < 2 || g_strv_length (values) > 4) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_ARGS, + "Invalid arguments: filename required"); + return FALSE; + } + + if (g_strv_length (values) > 2) + firmware_type_src = g_strdup (values[2]); + if (g_strv_length (values) > 3) + firmware_type_dst = g_strdup (values[3]); + + /* load file */ + blob_src = fu_common_get_contents_bytes (values[0], error); + if (blob_src == NULL) + return FALSE; + + /* load engine */ + if (!fu_engine_load (priv->engine, FU_ENGINE_LOAD_FLAG_NO_ENUMERATE, error)) + return FALSE; + + /* find the GType to use */ + if (firmware_type_src == NULL) + firmware_type_src = fu_util_prompt_for_firmware_type (priv, error); + if (firmware_type_src == NULL) + return FALSE; + if (firmware_type_dst == NULL) + firmware_type_dst = fu_util_prompt_for_firmware_type (priv, error); + if (firmware_type_dst == NULL) + return FALSE; + gtype_src = fu_engine_get_firmware_gtype_by_id (priv->engine, firmware_type_src); + if (gtype_src == G_TYPE_INVALID) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + "GType %s not supported", firmware_type_src); + return FALSE; + } + gtype_dst = fu_engine_get_firmware_gtype_by_id (priv->engine, firmware_type_dst); + if (gtype_dst == G_TYPE_INVALID) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + "GType %s not supported", firmware_type_dst); + return FALSE; + } + firmware_src = g_object_new (gtype_src, NULL); + if (!fu_firmware_parse (firmware_src, blob_src, priv->flags, error)) + return FALSE; + str_src = fu_firmware_to_string (firmware_src); + g_print ("%s", str_src); + + /* copy images */ + firmware_dst = g_object_new (gtype_dst, NULL); + images = fu_firmware_get_images (firmware_src); + for (guint i = 0; i < images->len; i++) { + FuFirmwareImage *img = g_ptr_array_index (images, i); + fu_firmware_add_image (firmware_dst, img); + } + + /* write new file */ + blob_dst = fu_firmware_write (firmware_dst, error); + if (blob_dst == NULL) + return FALSE; + if (!fu_common_set_contents_bytes (values[1], blob_dst, error)) + return FALSE; + str_dst = fu_firmware_to_string (firmware_dst); + g_print ("%s", str_dst); + + /* success */ + return TRUE; +} + static gboolean fu_util_verify_update (FuUtilPrivate *priv, gchar **values, GError **error) { @@ -1946,6 +2036,12 @@ main (int argc, char *argv[]) /* TRANSLATORS: command description */ _("Read a firmware blob from a device"), fu_util_firmware_read); + fu_util_cmd_array_add (cmd_array, + "firmware-convert", + "FILENAME-SRC FILENAME-DST [FIRMWARE-TYPE-SRC] [FIRMWARE-TYPE-DST]", + /* TRANSLATORS: command description */ + _("Convert a firmware file"), + fu_util_firmware_convert); fu_util_cmd_array_add (cmd_array, "firmware-parse", "FILENAME [FIRMWARE-TYPE]",