mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-17 07:02:56 +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'
|
'smbios-dump'
|
||||||
'attach'
|
'attach'
|
||||||
'detach'
|
'detach'
|
||||||
|
'firmware-read'
|
||||||
'verify-update'
|
'verify-update'
|
||||||
'watch'
|
'watch'
|
||||||
)
|
)
|
||||||
@ -86,7 +87,7 @@ _fwupdtool()
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
case $command in
|
case $command in
|
||||||
get-details|install|install-blob)
|
get-details|install|install-blob|firmware-read)
|
||||||
#find files
|
#find files
|
||||||
if [[ "$prev" = "$command" ]]; then
|
if [[ "$prev" = "$command" ]]; then
|
||||||
_filedir
|
_filedir
|
||||||
|
@ -2082,6 +2082,35 @@ fu_engine_update (FuEngine *self,
|
|||||||
return TRUE;
|
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
|
gboolean
|
||||||
fu_engine_install_blob (FuEngine *self,
|
fu_engine_install_blob (FuEngine *self,
|
||||||
FuDevice *device,
|
FuDevice *device,
|
||||||
|
@ -96,6 +96,10 @@ gboolean fu_engine_verify (FuEngine *self,
|
|||||||
gboolean fu_engine_verify_update (FuEngine *self,
|
gboolean fu_engine_verify_update (FuEngine *self,
|
||||||
const gchar *device_id,
|
const gchar *device_id,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GBytes *fu_engine_firmware_read (FuEngine *self,
|
||||||
|
FuDevice *device,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error);
|
||||||
gboolean fu_engine_modify_remote (FuEngine *self,
|
gboolean fu_engine_modify_remote (FuEngine *self,
|
||||||
const gchar *remote_id,
|
const gchar *remote_id,
|
||||||
const gchar *key,
|
const gchar *key,
|
||||||
|
@ -39,6 +39,7 @@ typedef enum {
|
|||||||
FU_UTIL_OPERATION_UNKNOWN,
|
FU_UTIL_OPERATION_UNKNOWN,
|
||||||
FU_UTIL_OPERATION_UPDATE,
|
FU_UTIL_OPERATION_UPDATE,
|
||||||
FU_UTIL_OPERATION_INSTALL,
|
FU_UTIL_OPERATION_INSTALL,
|
||||||
|
FU_UTIL_OPERATION_READ,
|
||||||
FU_UTIL_OPERATION_LAST
|
FU_UTIL_OPERATION_LAST
|
||||||
} FuUtilOperation;
|
} FuUtilOperation;
|
||||||
|
|
||||||
@ -558,6 +559,11 @@ fu_util_update_device_changed_cb (FwupdClient *client,
|
|||||||
str = g_strdup_printf (_("Installing on %s…"),
|
str = g_strdup_printf (_("Installing on %s…"),
|
||||||
fwupd_device_get_name (device));
|
fwupd_device_get_name (device));
|
||||||
fu_progressbar_set_title (priv->progressbar, str);
|
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 {
|
} else {
|
||||||
g_warning ("no FuUtilOperation set");
|
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);
|
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
|
static gint
|
||||||
fu_util_install_task_sort_cb (gconstpointer a, gconstpointer b)
|
fu_util_install_task_sort_cb (gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
@ -1685,6 +1747,12 @@ main (int argc, char *argv[])
|
|||||||
/* TRANSLATORS: command description */
|
/* TRANSLATORS: command description */
|
||||||
_("Update the stored metadata with current contents"),
|
_("Update the stored metadata with current contents"),
|
||||||
fu_util_verify_update);
|
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,
|
fu_util_cmd_array_add (cmd_array,
|
||||||
"firmware-parse",
|
"firmware-parse",
|
||||||
"FILENAME [FIRMWARE_TYPE]",
|
"FILENAME [FIRMWARE_TYPE]",
|
||||||
|
Loading…
Reference in New Issue
Block a user