diff --git a/libfwupd/fwupd-enums.c b/libfwupd/fwupd-enums.c index af349107f..a35cf31e7 100644 --- a/libfwupd/fwupd-enums.c +++ b/libfwupd/fwupd-enums.c @@ -199,6 +199,8 @@ fwupd_device_flag_to_string (FwupdDeviceFlags device_flag) return "skips-restart"; if (device_flag == FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES) return "has-multiple-branches"; + if (device_flag == FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL) + return "backup-before-install"; if (device_flag == FWUPD_DEVICE_FLAG_UNKNOWN) return "unknown"; return NULL; @@ -299,6 +301,8 @@ fwupd_device_flag_from_string (const gchar *device_flag) return FWUPD_DEVICE_FLAG_SKIPS_RESTART; if (g_strcmp0 (device_flag, "has-multiple-branches") == 0) return FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES; + if (g_strcmp0 (device_flag, "backup-before-install") == 0) + return FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL; return FWUPD_DEVICE_FLAG_UNKNOWN; } diff --git a/libfwupd/fwupd-enums.h b/libfwupd/fwupd-enums.h index 785a28a72..cda52db1f 100644 --- a/libfwupd/fwupd-enums.h +++ b/libfwupd/fwupd-enums.h @@ -127,6 +127,7 @@ typedef enum { * @FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN: Device is updatable but should not be called by the client * @FWUPD_DEVICE_FLAG_SKIPS_RESTART: Device relies upon activation or power cycle to load firmware * @FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES: Device supports switching to a different stream of firmware + * @FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL: Device firmware should be saved before installing firmware * * The device flags. **/ @@ -171,6 +172,7 @@ typedef enum { #define FWUPD_DEVICE_FLAG_UPDATABLE_HIDDEN (1llu << 37) /* Since: 1.4.1 */ #define FWUPD_DEVICE_FLAG_SKIPS_RESTART (1llu << 38) /* Since: 1.5.0 */ #define FWUPD_DEVICE_FLAG_HAS_MULTIPLE_BRANCHES (1llu << 39) /* Since: 1.5.0 */ +#define FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL (1llu << 40) /* Since: 1.5.0 */ #define FWUPD_DEVICE_FLAG_UNKNOWN G_MAXUINT64 /* Since: 0.7.3 */ typedef guint64 FwupdDeviceFlags; diff --git a/libfwupdplugin/fu-plugin.c b/libfwupdplugin/fu-plugin.c index 027884de9..f7df74d68 100644 --- a/libfwupdplugin/fu-plugin.c +++ b/libfwupdplugin/fu-plugin.c @@ -1052,6 +1052,32 @@ fu_plugin_device_write_firmware (FuPlugin *self, FuDevice *device, locker = fu_device_locker_new (device, error); if (locker == NULL) return FALSE; + + /* back the old firmware up to /var/lib/fwupd */ + if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL)) { + g_autoptr(GBytes) fw_old = NULL; + g_autofree gchar *path = NULL; + g_autofree gchar *fn = NULL; + g_autofree gchar *localstatedir = NULL; + + fw_old = fu_device_dump_firmware (device, error); + if (fw_old == NULL) { + g_prefix_error (error, "failed to backup old firmware: "); + return FALSE; + } + localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG); + fn = g_strdup_printf ("%s.bin", fu_device_get_version (device)); + path = g_build_filename (localstatedir, + "backup", + fu_device_get_id (device), + fu_device_get_serial (device) != NULL ? + fu_device_get_serial (device) : + "default", + fn, NULL); + if (!fu_common_set_contents_bytes (path, fw_old, error)) + return FALSE; + } + return fu_device_write_firmware (device, fw, flags, error); } diff --git a/src/fu-util-common.c b/src/fu-util-common.c index c0cc85d1e..3daf56e3b 100644 --- a/src/fu-util-common.c +++ b/src/fu-util-common.c @@ -1077,6 +1077,10 @@ fu_util_device_flag_to_string (guint64 device_flag) /* TRANSLATORS: there is more than one supplier of the firmware */ return _("Device supports switching to a different branch of firmware"); } + if (device_flag == FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL) { + /* TRANSLATORS: save the old firmware to disk before installing the new one */ + return _("Device will backup firmware before installing"); + } if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_NAME) { /* skip */ return NULL;