mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-08 01:14:43 +00:00
trivial: Break apart fu_engine_install_blob() into sane chunks
This fixes a number of bugs, where the plugin changing was not always detected properly. It also means we always record a error failure if _install_blob() returns FALSE.
This commit is contained in:
parent
84af6e71f4
commit
03df0d5379
318
src/fu-engine.c
318
src/fu-engine.c
@ -1473,16 +1473,25 @@ fu_engine_install (FuEngine *self,
|
|||||||
"No cabinet archive to schedule");
|
"No cabinet archive to schedule");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return fu_plugin_runner_schedule_update (plugin,
|
return fu_plugin_runner_schedule_update (plugin, device, blob_cab, error);
|
||||||
device,
|
|
||||||
blob_cab,
|
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* install firmware blob */
|
/* install firmware blob */
|
||||||
version_orig = g_strdup (fu_device_get_version (device));
|
version_orig = g_strdup (fu_device_get_version (device));
|
||||||
if (!fu_engine_install_blob (self, device, blob_fw2, flags, error))
|
if (!fu_engine_install_blob (self, device, blob_fw2, flags, &error_local)) {
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_IDLE);
|
||||||
|
fu_device_set_update_state (device, FWUPD_UPDATE_STATE_FAILED);
|
||||||
|
fu_device_set_update_error (device, error_local->message);
|
||||||
|
if ((flags & FWUPD_INSTALL_FLAG_NO_HISTORY) == 0 &&
|
||||||
|
!fu_history_modify_device (self->history, device,
|
||||||
|
FU_HISTORY_FLAGS_MATCH_OLD_VERSION |
|
||||||
|
FU_HISTORY_FLAGS_MATCH_NEW_VERSION,
|
||||||
|
error)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
g_propagate_error (error, g_steal_pointer (&error_local));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* update database */
|
/* update database */
|
||||||
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT) ||
|
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT) ||
|
||||||
@ -1579,22 +1588,167 @@ fu_engine_get_device_by_id (FuEngine *self, const gchar *device_id, GError **err
|
|||||||
return g_steal_pointer (&device2);
|
return g_steal_pointer (&device2);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
fu_engine_install_blob (FuEngine *self,
|
fu_engine_update_prepare (FuEngine *self,
|
||||||
FuDevice *device_orig,
|
FwupdInstallFlags flags,
|
||||||
|
const gchar *device_id,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GPtrArray *plugins = fu_plugin_list_get_all (self->plugin_list);
|
||||||
|
g_autoptr(FuDevice) device = NULL;
|
||||||
|
|
||||||
|
/* the device and plugin both may have changed */
|
||||||
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL)
|
||||||
|
return FALSE;
|
||||||
|
for (guint j = 0; j < plugins->len; j++) {
|
||||||
|
FuPlugin *plugin_tmp = g_ptr_array_index (plugins, j);
|
||||||
|
if (!fu_plugin_runner_update_prepare (plugin_tmp, flags, device, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_update_cleanup (FuEngine *self,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
const gchar *device_id,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GPtrArray *plugins = fu_plugin_list_get_all (self->plugin_list);
|
||||||
|
g_autoptr(FuDevice) device = NULL;
|
||||||
|
|
||||||
|
/* the device and plugin both may have changed */
|
||||||
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL)
|
||||||
|
return FALSE;
|
||||||
|
for (guint j = 0; j < plugins->len; j++) {
|
||||||
|
FuPlugin *plugin_tmp = g_ptr_array_index (plugins, j);
|
||||||
|
if (!fu_plugin_runner_update_cleanup (plugin_tmp, flags, device, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_update_detach (FuEngine *self, const gchar *device_id, GError **error)
|
||||||
|
{
|
||||||
|
FuPlugin *plugin;
|
||||||
|
g_autoptr(FuDevice) device = NULL;
|
||||||
|
|
||||||
|
/* the device and plugin both may have changed */
|
||||||
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL)
|
||||||
|
return FALSE;
|
||||||
|
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
||||||
|
fu_device_get_plugin (device),
|
||||||
|
error);
|
||||||
|
if (plugin == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_plugin_runner_update_detach (plugin, device, error))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_update_attach (FuEngine *self, const gchar *device_id, GError **error)
|
||||||
|
{
|
||||||
|
FuPlugin *plugin;
|
||||||
|
g_autoptr(FuDevice) device = NULL;
|
||||||
|
|
||||||
|
/* the device and plugin both may have changed */
|
||||||
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL) {
|
||||||
|
g_prefix_error (error, "failed to get device after update: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
||||||
|
fu_device_get_plugin (device),
|
||||||
|
error);
|
||||||
|
if (plugin == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_plugin_runner_update_attach (plugin, device, error))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_update_reload (FuEngine *self, const gchar *device_id, GError **error)
|
||||||
|
{
|
||||||
|
FuPlugin *plugin;
|
||||||
|
g_autoptr(FuDevice) device = NULL;
|
||||||
|
|
||||||
|
/* the device and plugin both may have changed */
|
||||||
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL) {
|
||||||
|
g_prefix_error (error, "failed to get device after update: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
||||||
|
fu_device_get_plugin (device),
|
||||||
|
error);
|
||||||
|
if (plugin == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_plugin_runner_update_reload (plugin, device, error)) {
|
||||||
|
g_prefix_error (error, "failed to reload device: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_update (FuEngine *self,
|
||||||
|
const gchar *device_id,
|
||||||
GBytes *blob_fw2,
|
GBytes *blob_fw2,
|
||||||
FwupdInstallFlags flags,
|
FwupdInstallFlags flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
FuPlugin *plugin;
|
FuPlugin *plugin;
|
||||||
GPtrArray *plugins;
|
g_autoptr(FuDevice) device = NULL;
|
||||||
g_autofree gchar *device_id_orig = NULL;
|
|
||||||
g_autoptr(FuDevice) device = g_object_ref (device_orig);
|
/* the device and plugin both may have changed */
|
||||||
g_autoptr(GError) error_local = NULL;
|
device = fu_engine_get_device_by_id (self, device_id, error);
|
||||||
|
if (device == NULL) {
|
||||||
|
g_prefix_error (error, "failed to get device after detach: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
||||||
|
fu_device_get_plugin (device),
|
||||||
|
error);
|
||||||
|
if (plugin == NULL)
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_plugin_runner_update (plugin, device, blob_fw2, flags, error)) {
|
||||||
|
g_autoptr(GError) error_attach = NULL;
|
||||||
|
g_autoptr(GError) error_cleanup = NULL;
|
||||||
|
|
||||||
|
/* attack back into runtime then cleanup */
|
||||||
|
if (!fu_plugin_runner_update_attach (plugin,
|
||||||
|
device,
|
||||||
|
&error_attach)) {
|
||||||
|
g_warning ("failed to attach device after failed update: %s",
|
||||||
|
error_attach->message);
|
||||||
|
}
|
||||||
|
if (!fu_engine_update_cleanup (self, flags, device_id, &error_cleanup)) {
|
||||||
|
g_warning ("failed to update-cleanup after failed update: %s",
|
||||||
|
error_cleanup->message);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
fu_engine_install_blob (FuEngine *self,
|
||||||
|
FuDevice *device,
|
||||||
|
GBytes *blob_fw,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree gchar *device_id = NULL;
|
||||||
g_autoptr(GTimer) timer = g_timer_new ();
|
g_autoptr(GTimer) timer = g_timer_new ();
|
||||||
|
|
||||||
/* test the firmware is not an empty blob */
|
/* test the firmware is not an empty blob */
|
||||||
if (g_bytes_get_size (blob_fw2) == 0) {
|
if (g_bytes_get_size (blob_fw) == 0) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
@ -1602,147 +1756,33 @@ fu_engine_install_blob (FuEngine *self,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the plugin */
|
|
||||||
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
|
||||||
fu_device_get_plugin (device),
|
|
||||||
error);
|
|
||||||
if (plugin == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* signal to all the plugins the update is about to happen */
|
|
||||||
plugins = fu_plugin_list_get_all (self->plugin_list);
|
|
||||||
for (guint j = 0; j < plugins->len; j++) {
|
|
||||||
FuPlugin *plugin_tmp = g_ptr_array_index (plugins, j);
|
|
||||||
if (!fu_plugin_runner_update_prepare (plugin_tmp, flags, device, error))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the chosen device ID in case the device goes away */
|
|
||||||
device_id_orig = g_strdup (fu_device_get_id (device));
|
|
||||||
|
|
||||||
/* in case another device caused us to go into replug before starting */
|
|
||||||
g_clear_object (&device);
|
|
||||||
device = fu_engine_get_device_by_id (self, device_id_orig, error);
|
|
||||||
if (device == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* mark this as modified even if we actually fail to do the update */
|
/* mark this as modified even if we actually fail to do the update */
|
||||||
fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
|
fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
|
||||||
|
|
||||||
/* do the update */
|
/* signal to all the plugins the update is about to happen */
|
||||||
if (!fu_plugin_runner_update_detach (plugin, device, &error_local)) {
|
device_id = g_strdup (fu_device_get_id (device));
|
||||||
fu_device_set_update_state (device, FWUPD_UPDATE_STATE_FAILED);
|
if (!fu_engine_update_prepare (self, flags, device_id, error))
|
||||||
fu_device_set_update_error (device, error_local->message);
|
|
||||||
if ((flags & FWUPD_INSTALL_FLAG_NO_HISTORY) == 0 &&
|
|
||||||
!fu_history_modify_device (self->history, device,
|
|
||||||
FU_HISTORY_FLAGS_MATCH_OLD_VERSION,
|
|
||||||
error)) {
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
g_propagate_error (error, g_steal_pointer (&error_local));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_clear_object (&device);
|
|
||||||
device = fu_engine_get_device_by_id (self, device_id_orig, error);
|
|
||||||
if (device == NULL) {
|
|
||||||
g_prefix_error (error, "failed to get device after detach: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get new plugin after detach */
|
/* detach to bootloader mode */
|
||||||
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
if (!fu_engine_update_detach (self, device_id, error))
|
||||||
fu_device_get_plugin (device),
|
|
||||||
error);
|
|
||||||
if (plugin == NULL)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_plugin_runner_update (plugin,
|
|
||||||
device,
|
|
||||||
blob_fw2,
|
|
||||||
flags,
|
|
||||||
&error_local)) {
|
|
||||||
g_autoptr(GError) error_attach = NULL;
|
|
||||||
|
|
||||||
/* save to database */
|
/* install */
|
||||||
fu_device_set_update_state (device, FWUPD_UPDATE_STATE_FAILED);
|
if (!fu_engine_update (self, device_id, blob_fw, flags, error))
|
||||||
fu_device_set_update_error (device, error_local->message);
|
|
||||||
if ((flags & FWUPD_INSTALL_FLAG_NO_HISTORY) == 0 &&
|
|
||||||
!fu_history_modify_device (self->history, device,
|
|
||||||
FU_HISTORY_FLAGS_MATCH_OLD_VERSION,
|
|
||||||
error)) {
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
g_propagate_error (error, g_steal_pointer (&error_local));
|
|
||||||
|
|
||||||
/* attack back into runtime */
|
/* attach into runtime mode */
|
||||||
if (!fu_plugin_runner_update_attach (plugin,
|
if (!fu_engine_update_attach (self, device_id, error))
|
||||||
device,
|
|
||||||
&error_attach)) {
|
|
||||||
g_warning ("failed to attach device after failed update: %s",
|
|
||||||
error_attach->message);
|
|
||||||
}
|
|
||||||
for (guint j = 0; j < plugins->len; j++) {
|
|
||||||
FuPlugin *plugin_tmp = g_ptr_array_index (plugins, j);
|
|
||||||
g_autoptr(GError) error_cleanup = NULL;
|
|
||||||
if (!fu_plugin_runner_update_cleanup (plugin_tmp,
|
|
||||||
flags,
|
|
||||||
device,
|
|
||||||
&error_cleanup)) {
|
|
||||||
g_warning ("failed to update-cleanup "
|
|
||||||
"after failed update: %s",
|
|
||||||
error_cleanup->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fu_device_set_status (device, FWUPD_STATUS_IDLE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_clear_object (&device);
|
|
||||||
device = fu_engine_get_device_by_id (self, device_id_orig, error);
|
|
||||||
if (device == NULL) {
|
|
||||||
g_prefix_error (error, "failed to get device after update: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!fu_plugin_runner_update_attach (plugin, device, &error_local)) {
|
|
||||||
fu_device_set_update_state (device, FWUPD_UPDATE_STATE_FAILED);
|
|
||||||
fu_device_set_update_error (device, error_local->message);
|
|
||||||
if ((flags & FWUPD_INSTALL_FLAG_NO_HISTORY) == 0 &&
|
|
||||||
!fu_history_modify_device (self->history, device,
|
|
||||||
FU_HISTORY_FLAGS_MATCH_OLD_VERSION |
|
|
||||||
FU_HISTORY_FLAGS_MATCH_NEW_VERSION,
|
|
||||||
error)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_propagate_error (error, g_steal_pointer (&error_local));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
g_clear_object (&device);
|
|
||||||
device = fu_engine_get_device_by_id (self, device_id_orig, error);
|
|
||||||
if (device == NULL) {
|
|
||||||
g_prefix_error (error, "failed to get device after attach: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get new plugin after attach */
|
|
||||||
plugin = fu_plugin_list_find_by_name (self->plugin_list,
|
|
||||||
fu_device_get_plugin (device),
|
|
||||||
error);
|
|
||||||
if (plugin == NULL)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* get the new version number */
|
/* get the new version number */
|
||||||
if (!fu_plugin_runner_update_reload (plugin, device, error)) {
|
if (!fu_engine_update_reload (self, device_id, error))
|
||||||
g_prefix_error (error, "failed to reload device: ");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
/* signal to all the plugins the update has happened */
|
/* signal to all the plugins the update has happened */
|
||||||
for (guint j = 0; j < plugins->len; j++) {
|
if (!fu_engine_update_cleanup (self, flags, device_id, error))
|
||||||
FuPlugin *plugin_tmp = g_ptr_array_index (plugins, j);
|
return FALSE;
|
||||||
g_autoptr(GError) error_cleanup = NULL;
|
|
||||||
if (!fu_plugin_runner_update_cleanup (plugin_tmp, flags, device, &error_cleanup)) {
|
|
||||||
g_warning ("failed to update-cleanup: %s",
|
|
||||||
error_cleanup->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make the UI update */
|
/* make the UI update */
|
||||||
fu_engine_set_status (self, FWUPD_STATUS_IDLE);
|
fu_engine_set_status (self, FWUPD_STATUS_IDLE);
|
||||||
|
Loading…
Reference in New Issue
Block a user