uefi-capsule: Require at least 80MB free in the ESP

See https://github.com/fwupd/firmware-lenovo/issues/257
This commit is contained in:
Richard Hughes 2023-02-15 15:27:22 +00:00
parent 336494190d
commit b25e0f3a28
4 changed files with 38 additions and 24 deletions

View File

@ -437,7 +437,7 @@ fu_uefi_capsule_plugin_load_config(FuPlugin *plugin, FuDevice *device)
{ {
gboolean disable_shim; gboolean disable_shim;
gboolean fallback_removable_path; gboolean fallback_removable_path;
guint64 sz_reqd = FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE; guint64 sz_reqd = 0;
g_autofree gchar *require_esp_free_space = NULL; g_autofree gchar *require_esp_free_space = NULL;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
@ -448,7 +448,7 @@ fu_uefi_capsule_plugin_load_config(FuPlugin *plugin, FuDevice *device)
g_warning("invalid ESP free space specified: %s", error_local->message); g_warning("invalid ESP free space specified: %s", error_local->message);
} }
} }
fu_device_set_metadata_integer(device, "RequireESPFreeSpace", sz_reqd); fu_uefi_device_set_require_esp_free_space(FU_UEFI_DEVICE(device), sz_reqd);
/* shim used for SB or not? */ /* shim used for SB or not? */
disable_shim = fu_plugin_get_config_value_boolean(plugin, "DisableShimForSecureBoot"); disable_shim = fu_plugin_get_config_value_boolean(plugin, "DisableShimForSecureBoot");

View File

@ -61,9 +61,6 @@ typedef struct __attribute__((__packed__)) {
guint32 status; guint32 status;
} efi_update_info_t; } efi_update_info_t;
/* the biggest size SPI part currently seen */
#define FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE (32 * 1024 * 1024)
gchar * gchar *
fu_uefi_get_fallback_app_path(FuDevice *device, fu_uefi_get_fallback_app_path(FuDevice *device,
const gchar *esp_path, const gchar *esp_path,

View File

@ -30,6 +30,7 @@ typedef struct {
guint64 fmp_hardware_instance; guint64 fmp_hardware_instance;
gboolean missing_header; gboolean missing_header;
gboolean automounted_esp; gboolean automounted_esp;
gsize require_esp_free_space;
} FuUefiDevicePrivate; } FuUefiDevicePrivate;
G_DEFINE_TYPE_WITH_PRIVATE(FuUefiDevice, fu_uefi_device, FU_TYPE_DEVICE) G_DEFINE_TYPE_WITH_PRIVATE(FuUefiDevice, fu_uefi_device, FU_TYPE_DEVICE)
@ -134,10 +135,7 @@ fu_uefi_device_to_string(FuDevice *device, guint idt, GString *str)
if (priv->esp != NULL) { if (priv->esp != NULL) {
fu_string_append(str, idt, "EspId", fu_volume_get_id(priv->esp)); fu_string_append(str, idt, "EspId", fu_volume_get_id(priv->esp));
} }
fu_string_append_ku(str, fu_string_append_ku(str, idt, "RequireESPFreeSpace", priv->require_esp_free_space);
idt,
"RequireESPFreeSpace",
fu_device_get_metadata_integer(device, "RequireESPFreeSpace"));
} }
static void static void
@ -254,6 +252,14 @@ fu_uefi_device_set_status(FuUefiDevice *self, FuUefiDeviceStatus status)
fu_device_set_update_error(FU_DEVICE(self), err_msg); fu_device_set_update_error(FU_DEVICE(self), err_msg);
} }
void
fu_uefi_device_set_require_esp_free_space(FuUefiDevice *self, gsize require_esp_free_space)
{
FuUefiDevicePrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FU_IS_UEFI_DEVICE(self));
priv->require_esp_free_space = require_esp_free_space;
}
guint32 guint32
fu_uefi_device_get_capsule_flags(FuUefiDevice *self) fu_uefi_device_get_capsule_flags(FuUefiDevice *self)
{ {
@ -495,19 +501,6 @@ fu_uefi_device_write_update_info(FuUefiDevice *self,
error); error);
} }
static gboolean
fu_uefi_device_check_esp_free(FuDevice *device, GError **error)
{
FuUefiDevice *self = FU_UEFI_DEVICE(device);
FuUefiDevicePrivate *priv = GET_PRIVATE(self);
guint64 sz_reqd = fu_device_get_metadata_integer(device, "RequireESPFreeSpace");
if (sz_reqd == G_MAXUINT) {
g_debug("maximum size is not configured");
return TRUE;
}
return fu_volume_check_free_space(priv->esp, sz_reqd, error);
}
static gboolean static gboolean
fu_uefi_check_asset(FuDevice *device, GError **error) fu_uefi_check_asset(FuDevice *device, GError **error)
{ {
@ -573,8 +566,6 @@ fu_uefi_device_prepare(FuDevice *device,
/* sanity checks */ /* sanity checks */
if (!fu_uefi_device_cleanup_esp(device, error)) if (!fu_uefi_device_cleanup_esp(device, error))
return FALSE; return FALSE;
if (!fu_uefi_device_check_esp_free(device, error))
return FALSE;
if (!fu_uefi_check_asset(device, error)) if (!fu_uefi_check_asset(device, error))
return FALSE; return FALSE;
@ -677,6 +668,29 @@ fu_uefi_device_get_esp_path(FuUefiDevice *self)
return fu_volume_get_mount_point(priv->esp); return fu_volume_get_mount_point(priv->esp);
} }
static FuFirmware *
fu_uefi_device_prepare_firmware(FuDevice *device,
GBytes *fw,
FwupdInstallFlags flags,
GError **error)
{
FuUefiDevice *self = FU_UEFI_DEVICE(device);
FuUefiDevicePrivate *priv = GET_PRIVATE(self);
gsize sz_reqd = priv->require_esp_free_space;
/* check there is enough space in the ESP */
if (sz_reqd == 0) {
g_debug("required ESP free space is not configured, using 2 x %uMB + 20MB",
(guint)g_bytes_get_size(fw) / (1024 * 1024));
sz_reqd = g_bytes_get_size(fw) * 2 + (20u * 1024 * 1024);
}
if (!fu_volume_check_free_space(priv->esp, sz_reqd, error))
return NULL;
/* success */
return fu_firmware_new_from_bytes(fw);
}
static void static void
fu_uefi_device_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) fu_uefi_device_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{ {
@ -781,6 +795,7 @@ fu_uefi_device_class_init(FuUefiDeviceClass *klass)
object_class->finalize = fu_uefi_device_finalize; object_class->finalize = fu_uefi_device_finalize;
klass_device->to_string = fu_uefi_device_to_string; klass_device->to_string = fu_uefi_device_to_string;
klass_device->probe = fu_uefi_device_probe; klass_device->probe = fu_uefi_device_probe;
klass_device->prepare_firmware = fu_uefi_device_prepare_firmware;
klass_device->prepare = fu_uefi_device_prepare; klass_device->prepare = fu_uefi_device_prepare;
klass_device->cleanup = fu_uefi_device_cleanup; klass_device->cleanup = fu_uefi_device_cleanup;
klass_device->report_metadata_pre = fu_uefi_device_report_metadata_pre; klass_device->report_metadata_pre = fu_uefi_device_report_metadata_pre;

View File

@ -134,3 +134,5 @@ GBytes *
fu_uefi_device_fixup_firmware(FuUefiDevice *self, GBytes *fw, GError **error); fu_uefi_device_fixup_firmware(FuUefiDevice *self, GBytes *fw, GError **error);
void void
fu_uefi_device_set_status(FuUefiDevice *self, FuUefiDeviceStatus status); 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);