mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-16 10:06:41 +00:00
Allow verifying the device image itself from fwupdtool
To debug flashing failures it's sometimes requried to get a SPI dump of the hardware to analysis. Add a debug-only command that lets us dump the device from the engine.
This commit is contained in:
parent
51a869a01d
commit
a58510b246
@ -21,6 +21,7 @@ _fwupdtool_cmd_list=(
|
||||
'smbios-dump'
|
||||
'attach'
|
||||
'detach'
|
||||
'firmware-read'
|
||||
'verify-update'
|
||||
'watch'
|
||||
)
|
||||
@ -86,7 +87,7 @@ _fwupdtool()
|
||||
esac
|
||||
|
||||
case $command in
|
||||
get-details|install|install-blob)
|
||||
get-details|install|install-blob|firmware-read)
|
||||
#find files
|
||||
if [[ "$prev" = "$command" ]]; then
|
||||
_filedir
|
||||
|
@ -2082,6 +2082,35 @@ fu_engine_update (FuEngine *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
fu_engine_firmware_read (FuEngine *self,
|
||||
FuDevice *device,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(FuDeviceLocker) locker = NULL;
|
||||
g_autoptr(FuFirmware) firmware = NULL;
|
||||
|
||||
/* open, detach, read, attach, serialize */
|
||||
locker = fu_device_locker_new (device, error);
|
||||
if (locker == NULL)
|
||||
return NULL;
|
||||
if (!fu_device_detach (device, error))
|
||||
return NULL;
|
||||
firmware = fu_device_read_firmware (device, error);
|
||||
if (firmware == NULL) {
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
if (!fu_device_attach (device, &error_local)) {
|
||||
g_warning ("failed to attach after read image failure: %s",
|
||||
error_local->message);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (!fu_device_attach (device, error))
|
||||
return NULL;
|
||||
return fu_firmware_write (firmware, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_engine_install_blob (FuEngine *self,
|
||||
FuDevice *device,
|
||||
|
@ -96,6 +96,10 @@ gboolean fu_engine_verify (FuEngine *self,
|
||||
gboolean fu_engine_verify_update (FuEngine *self,
|
||||
const gchar *device_id,
|
||||
GError **error);
|
||||
GBytes *fu_engine_firmware_read (FuEngine *self,
|
||||
FuDevice *device,
|
||||
FwupdInstallFlags flags,
|
||||
GError **error);
|
||||
gboolean fu_engine_modify_remote (FuEngine *self,
|
||||
const gchar *remote_id,
|
||||
const gchar *key,
|
||||
|
@ -39,6 +39,7 @@ typedef enum {
|
||||
FU_UTIL_OPERATION_UNKNOWN,
|
||||
FU_UTIL_OPERATION_UPDATE,
|
||||
FU_UTIL_OPERATION_INSTALL,
|
||||
FU_UTIL_OPERATION_READ,
|
||||
FU_UTIL_OPERATION_LAST
|
||||
} FuUtilOperation;
|
||||
|
||||
@ -558,6 +559,11 @@ fu_util_update_device_changed_cb (FwupdClient *client,
|
||||
str = g_strdup_printf (_("Installing on %s…"),
|
||||
fwupd_device_get_name (device));
|
||||
fu_progressbar_set_title (priv->progressbar, str);
|
||||
} else if (priv->current_operation == FU_UTIL_OPERATION_READ) {
|
||||
/* TRANSLATORS: %1 is a device name */
|
||||
str = g_strdup_printf (_("Reading from %s…"),
|
||||
fwupd_device_get_name (device));
|
||||
fu_progressbar_set_title (priv->progressbar, str);
|
||||
} else {
|
||||
g_warning ("no FuUtilOperation set");
|
||||
}
|
||||
@ -660,6 +666,62 @@ fu_util_install_blob (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
return fu_util_prompt_complete (priv->completion_flags, TRUE, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_util_firmware_read (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||
{
|
||||
g_autoptr(FuDevice) device = NULL;
|
||||
g_autoptr(GBytes) blob_empty = g_bytes_new (NULL, 0);
|
||||
g_autoptr(GBytes) blob_fw = NULL;
|
||||
|
||||
/* invalid args */
|
||||
if (g_strv_length (values) == 0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_ARGS,
|
||||
"Invalid arguments");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* file already exists */
|
||||
if ((priv->flags & FWUPD_INSTALL_FLAG_FORCE) == 0 &&
|
||||
g_file_test (values[0], G_FILE_TEST_EXISTS)) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_ARGS,
|
||||
"Filename already exists");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* write a zero lenth file to ensure the destination is writable to
|
||||
* avoid failing at the end of a potentially lengthy operation */
|
||||
if (!fu_common_set_contents_bytes (values[0], blob_empty, error))
|
||||
return FALSE;
|
||||
|
||||
/* load engine */
|
||||
if (!fu_util_start_engine (priv, FU_ENGINE_LOAD_FLAG_NONE, error))
|
||||
return FALSE;
|
||||
|
||||
/* get device */
|
||||
if (g_strv_length (values) >= 2) {
|
||||
device = fu_engine_get_device (priv->engine, values[1], error);
|
||||
if (device == NULL)
|
||||
return FALSE;
|
||||
} else {
|
||||
device = fu_util_prompt_for_device (priv, error);
|
||||
if (device == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
priv->current_operation = FU_UTIL_OPERATION_READ;
|
||||
g_signal_connect (priv->engine, "device-changed",
|
||||
G_CALLBACK (fu_util_update_device_changed_cb), priv);
|
||||
|
||||
/* dump firmware */
|
||||
blob_fw = fu_engine_firmware_read (priv->engine, device, priv->flags, error);
|
||||
if (blob_fw == NULL)
|
||||
return FALSE;
|
||||
return fu_common_set_contents_bytes (values[0], blob_fw, error);
|
||||
}
|
||||
|
||||
static gint
|
||||
fu_util_install_task_sort_cb (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
@ -1685,6 +1747,12 @@ main (int argc, char *argv[])
|
||||
/* TRANSLATORS: command description */
|
||||
_("Update the stored metadata with current contents"),
|
||||
fu_util_verify_update);
|
||||
fu_util_cmd_array_add (cmd_array,
|
||||
"firmware-read",
|
||||
"FILENAME [DEVICE-ID]",
|
||||
/* TRANSLATORS: command description */
|
||||
_("Read a firmware blob from a device"),
|
||||
fu_util_firmware_read);
|
||||
fu_util_cmd_array_add (cmd_array,
|
||||
"firmware-parse",
|
||||
"FILENAME [FIRMWARE_TYPE]",
|
||||
|
Loading…
Reference in New Issue
Block a user