diff --git a/plugins/uefi-capsule/fu-uefi-capsule-plugin.c b/plugins/uefi-capsule/fu-uefi-capsule-plugin.c index 83ef7a1f3..fc5583e82 100644 --- a/plugins/uefi-capsule/fu-uefi-capsule-plugin.c +++ b/plugins/uefi-capsule/fu-uefi-capsule-plugin.c @@ -437,6 +437,7 @@ static void fu_uefi_capsule_plugin_load_config(FuPlugin *plugin, FuDevice *device) { gboolean disable_shim; + gboolean enable_efi_debugging; guint64 sz_reqd = 0; g_autofree gchar *require_esp_free_space = NULL; g_autoptr(GError) error_local = NULL; @@ -454,6 +455,11 @@ fu_uefi_capsule_plugin_load_config(FuPlugin *plugin, FuDevice *device) disable_shim = fu_plugin_get_config_value_boolean(plugin, "DisableShimForSecureBoot"); if (!disable_shim) fu_device_add_private_flag(device, FU_UEFI_DEVICE_FLAG_USE_SHIM_FOR_SB); + + /* enable the fwupd.efi debug log? */ + enable_efi_debugging = fu_plugin_get_config_value_boolean(plugin, "EnableEfiDebugging"); + if (enable_efi_debugging) + fu_device_add_private_flag(device, FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING); } static gboolean diff --git a/plugins/uefi-capsule/fu-uefi-device.c b/plugins/uefi-capsule/fu-uefi-device.c index 6fe78427c..a122da046 100644 --- a/plugins/uefi-capsule/fu-uefi-device.c +++ b/plugins/uefi-capsule/fu-uefi-device.c @@ -650,12 +650,78 @@ fu_uefi_device_probe(FuDevice *device, GError **error) return TRUE; } +static void +fu_uefi_device_capture_efi_debugging(FuDevice *device) +{ + gsize sz = 0; + g_autofree gchar *str = NULL; + g_autofree guint16 *buf_ucs2 = NULL; + g_autofree guint8 *buf = NULL; + g_autoptr(GError) error_local = NULL; + + /* get the EFI variable contents */ + if (!fu_efivar_get_data(FU_EFIVAR_GUID_FWUPDATE, + "FWUPDATE_DEBUG_LOG", + &buf, + &sz, + NULL, + &error_local)) { + fu_device_set_update_error(device, error_local->message); + return; + } + + /* convert from UCS-2 to UTF-8, carefully */ + buf_ucs2 = g_new0(guint16, (sz / 2) + 1); + memcpy(buf_ucs2, buf, sz); + str = g_utf16_to_utf8(buf_ucs2, sz / 2, NULL, NULL, &error_local); + if (str == NULL) { + fu_device_set_update_error(device, error_local->message); + return; + } + + /* success */ + fu_device_set_update_error(device, str); +} + +gboolean +fu_uefi_device_perhaps_enable_debugging(FuUefiDevice *self, GError **error) +{ + if (fu_device_has_private_flag(FU_DEVICE(self), FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING)) { + const guint8 data = 1; + if (!fu_efivar_set_data(FU_EFIVAR_GUID_FWUPDATE, + "FWUPDATE_VERBOSE", + &data, + sizeof(data), + FU_EFIVAR_ATTR_NON_VOLATILE | + FU_EFIVAR_ATTR_BOOTSERVICE_ACCESS | + FU_EFIVAR_ATTR_RUNTIME_ACCESS, + error)) { + g_prefix_error(error, "failed to enable debugging: "); + return FALSE; + } + return TRUE; + } + + /* unset this */ + if (fu_efivar_exists(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE")) { + if (!fu_efivar_delete(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE", error)) + return FALSE; + } + + /* success */ + return TRUE; +} + static gboolean fu_uefi_device_get_results(FuDevice *device, GError **error) { FuUefiDevice *self = FU_UEFI_DEVICE(device); FuUefiDevicePrivate *priv = GET_PRIVATE(self); + /* capture EFI binary debug output */ + if (fu_device_has_private_flag(device, FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING)) + fu_uefi_device_capture_efi_debugging(device); + /* just set the update error */ fu_uefi_device_set_status(self, priv->last_attempt_status); return TRUE; @@ -764,6 +830,9 @@ fu_uefi_device_init(FuUefiDevice *self) fu_device_register_private_flag(FU_DEVICE(self), FU_UEFI_DEVICE_FLAG_NO_CAPSULE_HEADER_FIXUP, "no-capsule-header-fixup"); + fu_device_register_private_flag(FU_DEVICE(self), + FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING, + "enable-debugging"); } static void diff --git a/plugins/uefi-capsule/fu-uefi-device.h b/plugins/uefi-capsule/fu-uefi-device.h index 58aefc7c8..0d73c0cbe 100644 --- a/plugins/uefi-capsule/fu-uefi-device.h +++ b/plugins/uefi-capsule/fu-uefi-device.h @@ -84,6 +84,12 @@ typedef enum { * Do not prepend a plausible missing capsule header. */ #define FU_UEFI_DEVICE_FLAG_NO_CAPSULE_HEADER_FIXUP (1 << 7) +/** + * FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING: + * + * Enable debugging the EFI binary. + */ +#define FU_UEFI_DEVICE_FLAG_ENABLE_EFI_DEBUGGING (1 << 8) FuUefiDeviceKind fu_uefi_device_kind_from_string(const gchar *kind); @@ -130,3 +136,5 @@ void fu_uefi_device_set_status(FuUefiDevice *self, FuUefiDeviceStatus status); void fu_uefi_device_set_require_esp_free_space(FuUefiDevice *self, gsize require_esp_free_space); +gboolean +fu_uefi_device_perhaps_enable_debugging(FuUefiDevice *self, GError **error); diff --git a/plugins/uefi-capsule/fu-uefi-grub-device.c b/plugins/uefi-capsule/fu-uefi-grub-device.c index 2920cff6f..9a2ff0653 100644 --- a/plugins/uefi-capsule/fu-uefi-grub-device.c +++ b/plugins/uefi-capsule/fu-uefi-grub-device.c @@ -155,11 +155,11 @@ fu_uefi_grub_device_write_firmware(FuDevice *device, if (g_getenv("FWUPD_UEFI_TEST") != NULL) return TRUE; - /* delete the logs to save space; use fwupdate to debug the EFI binary */ - if (fu_efivar_exists(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE")) { - if (!fu_efivar_delete(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE", error)) - return FALSE; - } + /* enable debugging in the EFI binary */ + if (!fu_uefi_device_perhaps_enable_debugging(self, error)) + return FALSE; + + /* delete the old log to save space */ if (fu_efivar_exists(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_DEBUG_LOG")) { if (!fu_efivar_delete(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_DEBUG_LOG", error)) return FALSE; diff --git a/plugins/uefi-capsule/fu-uefi-nvram-device.c b/plugins/uefi-capsule/fu-uefi-nvram-device.c index 28413fb37..03c6f31ef 100644 --- a/plugins/uefi-capsule/fu-uefi-nvram-device.c +++ b/plugins/uefi-capsule/fu-uefi-nvram-device.c @@ -89,11 +89,11 @@ fu_uefi_nvram_device_write_firmware(FuDevice *device, if (!fu_bytes_set_contents(fn, fixed_fw, error)) return FALSE; - /* delete the logs to save space; use fwupdate to debug the EFI binary */ - if (fu_efivar_exists(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE")) { - if (!fu_efivar_delete(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_VERBOSE", error)) - return FALSE; - } + /* enable debugging in the EFI binary */ + if (!fu_uefi_device_perhaps_enable_debugging(self, error)) + return FALSE; + + /* delete the old log to save space */ if (fu_efivar_exists(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_DEBUG_LOG")) { if (!fu_efivar_delete(FU_EFIVAR_GUID_FWUPDATE, "FWUPDATE_DEBUG_LOG", error)) return FALSE; diff --git a/plugins/uefi-capsule/uefi_capsule.conf b/plugins/uefi-capsule/uefi_capsule.conf index 32edc4f04..d0056a750 100644 --- a/plugins/uefi-capsule/uefi_capsule.conf +++ b/plugins/uefi-capsule/uefi_capsule.conf @@ -12,3 +12,12 @@ # allow ignoring the CapsuleOnDisk support advertised by the firmware #DisableCapsuleUpdateOnDisk=true + +# enable the low-level debugging of fwupdx64.efi to the FWUPDATE_DEBUG_LOG EFI variable +# +# Note: enabling this option is going to fill up the NVRAM store much more quickly and +# should only be enabled when debugging an issue with the EFI binary +# +# This value also has no affect when using Capsule-on-Disk as the EFI helper binary is +# not being used +#EnableEfiDebugging=false