From f3f4ca0320e1c5bae4d50caa409301951bdb0c3e Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 25 Jun 2018 14:23:34 +0100 Subject: [PATCH] uefi: Clear the device status without using libfwup --- plugins/uefi/fu-plugin-uefi.c | 19 +------- plugins/uefi/fu-uefi-common.h | 24 ++++++++++ plugins/uefi/fu-uefi-device.c | 84 +++++++++++++++++++++++++++++++++++ plugins/uefi/fu-uefi-device.h | 6 +++ 4 files changed, 116 insertions(+), 17 deletions(-) diff --git a/plugins/uefi/fu-plugin-uefi.c b/plugins/uefi/fu-plugin-uefi.c index 68b10ac1b..7bd32c7f8 100644 --- a/plugins/uefi/fu-plugin-uefi.c +++ b/plugins/uefi/fu-plugin-uefi.c @@ -133,23 +133,8 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(fwup_resource_iter, _fwup_resource_iter_free); gboolean fu_plugin_clear_results (FuPlugin *plugin, FuDevice *device, GError **error) { - fwup_resource *re = NULL; - g_autoptr(fwup_resource_iter) iter = NULL; - - /* get the hardware we're referencing */ - fwup_resource_iter_create (&iter); - re = fu_plugin_uefi_find_resource (iter, device, error); - if (re == NULL) - return FALSE; - if (fwup_clear_status (re) < 0) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "Cannot create clear UEFI status for %s", - fu_device_get_guid_default (device)); - return FALSE; - } - return TRUE; + FuUefiDevice *device_uefi = FU_UEFI_DEVICE (device); + return fu_uefi_device_clear_status (device_uefi, error); } gboolean diff --git a/plugins/uefi/fu-uefi-common.h b/plugins/uefi/fu-uefi-common.h index e281917f1..6f277a7d9 100644 --- a/plugins/uefi/fu-uefi-common.h +++ b/plugins/uefi/fu-uefi-common.h @@ -10,9 +10,33 @@ #define __FU_UEFI_COMMON_H #include +#include G_BEGIN_DECLS +typedef struct __attribute__((__packed__)) { + guint16 year; + guint8 month; + guint8 day; + guint8 hour; + guint8 minute; + guint8 second; + guint8 pad1; + guint32 nanosecond; + guint16 timezone; + guint8 daylight; + guint8 pad2; +} efi_time_t; + +typedef struct __attribute__((__packed__)) { + guint32 update_info_version; + efi_guid_t guid; + guint32 capsule_flags; + guint64 hw_inst; + efi_time_t time_attempted; + guint32 status; +} efi_update_info_t; + gboolean fu_uefi_get_bitmap_size (const guint8 *buf, gsize bufsz, guint32 *width, diff --git a/plugins/uefi/fu-uefi-device.c b/plugins/uefi/fu-uefi-device.c index 5ff8ae427..e26b8ffb3 100644 --- a/plugins/uefi/fu-uefi-device.c +++ b/plugins/uefi/fu-uefi-device.c @@ -12,6 +12,7 @@ #include "fu-uefi-common.h" #include "fu-uefi-device.h" +#include "fu-uefi-vars.h" struct _FuUefiDevice { FuDevice parent_instance; @@ -141,6 +142,89 @@ fu_uefi_device_get_guid (FuUefiDevice *self) return self->fw_class; } +static gchar * +fu_uefi_device_build_varname (FuUefiDevice *self) +{ + return g_strdup_printf ("fwupdate-%s-%"G_GUINT64_FORMAT, + self->fw_class, + self->fmp_hardware_instance); +} + +static gboolean +fu_uefi_device_set_efivar (FuUefiDevice *self, + const guint8 *data, + gsize datasz, + GError **error) +{ + g_autofree gchar *varname = fu_uefi_device_build_varname (self); + return fu_uefi_vars_set_data (FU_UEFI_VARS_GUID_FWUPDATE, varname, + data, datasz, + FU_UEFI_VARS_ATTR_NON_VOLATILE | + FU_UEFI_VARS_ATTR_BOOTSERVICE_ACCESS | + FU_UEFI_VARS_ATTR_RUNTIME_ACCESS, + error); +} + +static gboolean +fu_uefi_device_info_from_databuf (efi_update_info_t *info, + const guint8 *data, + gsize sz, + GError **error) +{ + if (sz < sizeof(efi_update_info_t)) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "EFI variable is corrupt"); + return FALSE; + } + memcpy (info, data, sizeof(efi_update_info_t)); + return TRUE; +} + +gboolean +fu_uefi_device_get_update_info (FuUefiDevice *self, + efi_update_info_t *info, + GError **error) +{ + gsize datasz = 0; + g_autofree gchar *varname = fu_uefi_device_build_varname (self); + g_autofree guint8 *data = NULL; + + g_return_val_if_fail (FU_IS_UEFI_DEVICE (self), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* get the existing status */ + if (!fu_uefi_vars_get_data (FU_UEFI_VARS_GUID_FWUPDATE, varname, + &data, &datasz, NULL, error)) + return FALSE; + return fu_uefi_device_info_from_databuf (info, data, datasz, error); +} + +gboolean +fu_uefi_device_clear_status (FuUefiDevice *self, GError **error) +{ + efi_update_info_t info; + gsize datasz = 0; + g_autofree gchar *varname = fu_uefi_device_build_varname (self); + g_autofree guint8 *data = NULL; + + g_return_val_if_fail (FU_IS_UEFI_DEVICE (self), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* get the existing status */ + if (!fu_uefi_vars_get_data (FU_UEFI_VARS_GUID_FWUPDATE, varname, + &data, &datasz, NULL, error)) + return FALSE; + if (!fu_uefi_device_info_from_databuf (&info, data, datasz, error)) + return FALSE; + + /* save it back */ + info.status = FU_UEFI_DEVICE_STATUS_SUCCESS; + memcpy (data, &info, sizeof(info)); + return fu_uefi_device_set_efivar (self, data, datasz, error); +} + static void fu_uefi_device_init (FuUefiDevice *self) { diff --git a/plugins/uefi/fu-uefi-device.h b/plugins/uefi/fu-uefi-device.h index 679607a19..b2540fe66 100644 --- a/plugins/uefi/fu-uefi-device.h +++ b/plugins/uefi/fu-uefi-device.h @@ -12,6 +12,7 @@ #include #include "fu-plugin.h" +#include "fu-uefi-device.h" G_BEGIN_DECLS @@ -40,6 +41,8 @@ typedef enum { } FuUefiDeviceStatus; FuUefiDevice *fu_uefi_device_new_from_entry (const gchar *entry_path); +gboolean fu_uefi_device_clear_status (FuUefiDevice *self, + GError **error); FuUefiDeviceKind fu_uefi_device_get_kind (FuUefiDevice *self); const gchar *fu_uefi_device_get_guid (FuUefiDevice *self); guint32 fu_uefi_device_get_version (FuUefiDevice *self); @@ -50,6 +53,9 @@ guint64 fu_uefi_device_get_hardware_instance (FuUefiDevice *self); FuUefiDeviceStatus fu_uefi_device_get_status (FuUefiDevice *self); const gchar *fu_uefi_device_kind_to_string (FuUefiDeviceKind kind); const gchar *fu_uefi_device_status_to_string (FuUefiDeviceStatus status); +gboolean fu_uefi_device_get_update_info (FuUefiDevice *self, + efi_update_info_t *info, + GError **error); G_END_DECLS