uefi: Clear the device status without using libfwup

This commit is contained in:
Richard Hughes 2018-06-25 14:23:34 +01:00
parent 5585b00892
commit f3f4ca0320
4 changed files with 116 additions and 17 deletions

View File

@ -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

View File

@ -10,9 +10,33 @@
#define __FU_UEFI_COMMON_H
#include <glib.h>
#include <efivar.h>
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,

View File

@ -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)
{

View File

@ -12,6 +12,7 @@
#include <glib-object.h>
#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