From b47eee9a8a0cea2e700813ff090d9e5faf23f518 Mon Sep 17 00:00:00 2001 From: Hsieh-Tseng Shen Date: Thu, 5 Nov 2020 09:22:09 +0800 Subject: [PATCH] uefi: a new option for uefi configuration to use UEFI removable path Per discussion of #2513, Ubuntu Core was going to use UEFI removable path as default esp path, and it needs to change some parts around getting the esp path and searching the shim app path. Also, a new option "FallbacktoRemovablePath" is added into uefi.conf to be applied in this case, and it will be false by default. --- plugins/uefi/fu-plugin-uefi.c | 9 ++++++++- plugins/uefi/fu-uefi-bootmgr.c | 24 +++++++++++++++++------- plugins/uefi/fu-uefi-bootmgr.h | 5 ++++- plugins/uefi/fu-uefi-common.c | 17 +++++++++++++---- plugins/uefi/fu-uefi-common.h | 8 ++++++-- plugins/uefi/fu-uefi-device.c | 4 ++-- plugins/uefi/uefi.conf | 4 ++++ 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/plugins/uefi/fu-plugin-uefi.c b/plugins/uefi/fu-plugin-uefi.c index f4891cb26..434890e55 100644 --- a/plugins/uefi/fu-plugin-uefi.c +++ b/plugins/uefi/fu-plugin-uefi.c @@ -241,7 +241,7 @@ fu_plugin_uefi_write_splash_data (FuPlugin *plugin, /* save to a predicatable filename */ esp_path = fu_volume_get_mount_point (data->esp); - directory = fu_uefi_get_esp_path_for_os (esp_path); + directory = fu_uefi_get_esp_path_for_os (device, esp_path); basename = g_strdup_printf ("fwupd-%s.cap", FU_EFIVAR_GUID_UX_CAPSULE); fn = g_build_filename (directory, "fw", basename, NULL); if (!fu_common_mkdir_parent (fn, error)) @@ -425,6 +425,7 @@ static void fu_plugin_uefi_load_config (FuPlugin *plugin, FuDevice *device) { gboolean disable_shim; + gboolean fallback_removable_path; guint64 sz_reqd = FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE; g_autofree gchar *require_esp_free_space = NULL; @@ -439,6 +440,12 @@ fu_plugin_uefi_load_config (FuPlugin *plugin, FuDevice *device) fu_device_set_metadata_boolean (device, "RequireShimForSecureBoot", !disable_shim); + + /* check if using UEFI removeable path */ + fallback_removable_path = fu_plugin_get_config_value_boolean (plugin, "FallbacktoRemovablePath"); + fu_device_set_metadata_boolean (device, + "FallbacktoRemovablePath", + fallback_removable_path); } static void diff --git a/plugins/uefi/fu-uefi-bootmgr.c b/plugins/uefi/fu-uefi-bootmgr.c index ee7396728..50f8ac4ad 100644 --- a/plugins/uefi/fu-uefi-bootmgr.c +++ b/plugins/uefi/fu-uefi-bootmgr.c @@ -239,10 +239,11 @@ fu_uefi_copy_asset (const gchar *source, const gchar *target, GError **error) } gboolean -fu_uefi_bootmgr_bootnext (const gchar *esp_path, - const gchar *description, - FuUefiBootmgrFlags flags, - GError **error) +fu_uefi_bootmgr_bootnext (FuDevice *device, + const gchar *esp_path, + const gchar *description, + FuUefiBootmgrFlags flags, + GError **error) { const gchar *filepath; gboolean use_fwup_path = TRUE; @@ -273,14 +274,23 @@ fu_uefi_bootmgr_bootnext (const gchar *esp_path, secure_boot = fu_efivar_secure_boot_enabled (); if (secure_boot) { /* test to make sure shim is there if we need it */ - shim_app = fu_uefi_get_esp_app_path (esp_path, "shim", error); + shim_app = fu_uefi_get_esp_app_path (device, esp_path, "shim", error); if (shim_app == NULL) return FALSE; + /* try to fallback to use UEFI removable path if the shim path doesn't exist */ + if (!g_file_test (shim_app, G_FILE_TEST_EXISTS)) { + if (fu_device_get_metadata_boolean (device, "FallbacktoRemovablePath")) { + shim_app = fu_uefi_get_esp_app_path (device, esp_path, "boot", error); + if (shim_app == NULL) + return FALSE; + } + } + if (g_file_test (shim_app, G_FILE_TEST_EXISTS)) { /* use a custom copy of shim for firmware updates */ if (flags & FU_UEFI_BOOTMGR_FLAG_USE_SHIM_UNIQUE) { - shim_cpy = fu_uefi_get_esp_app_path (esp_path, "shimfwupd", error); + shim_cpy = fu_uefi_get_esp_app_path (device, esp_path, "shimfwupd", error); if (shim_cpy == NULL) return FALSE; if (!fu_uefi_cmp_asset (shim_app, shim_cpy)) { @@ -302,7 +312,7 @@ fu_uefi_bootmgr_bootnext (const gchar *esp_path, } /* test if correct asset in place */ - target_app = fu_uefi_get_esp_app_path (esp_path, "fwupd", error); + target_app = fu_uefi_get_esp_app_path (device, esp_path, "fwupd", error); if (target_app == NULL) return FALSE; if (!fu_uefi_cmp_asset (source_app, target_app)) { diff --git a/plugins/uefi/fu-uefi-bootmgr.h b/plugins/uefi/fu-uefi-bootmgr.h index eda193c55..d839f7010 100644 --- a/plugins/uefi/fu-uefi-bootmgr.h +++ b/plugins/uefi/fu-uefi-bootmgr.h @@ -10,6 +10,8 @@ #include #include +#include "fu-device.h" + typedef enum { FU_UEFI_BOOTMGR_FLAG_NONE = 0, FU_UEFI_BOOTMGR_FLAG_USE_SHIM_FOR_SB = 1 << 0, @@ -17,7 +19,8 @@ typedef enum { FU_UEFI_BOOTMGR_FLAG_LAST } FuUefiBootmgrFlags; -gboolean fu_uefi_bootmgr_bootnext (const gchar *esp_path, +gboolean fu_uefi_bootmgr_bootnext (FuDevice *device, + const gchar *esp_path, const gchar *description, FuUefiBootmgrFlags flags, GError **error); diff --git a/plugins/uefi/fu-uefi-common.c b/plugins/uefi/fu-uefi-common.c index a5b554293..04d393e8f 100644 --- a/plugins/uefi/fu-uefi-common.c +++ b/plugins/uefi/fu-uefi-common.c @@ -61,13 +61,16 @@ fu_uefi_bootmgr_get_suffix (GError **error) } gchar * -fu_uefi_get_esp_app_path (const gchar *esp_path, const gchar *cmd, GError **error) +fu_uefi_get_esp_app_path (FuDevice *device, + const gchar *esp_path, + const gchar *cmd, + GError **error) { const gchar *suffix = fu_uefi_bootmgr_get_suffix (error); g_autofree gchar *base = NULL; if (suffix == NULL) return NULL; - base = fu_uefi_get_esp_path_for_os (esp_path); + base = fu_uefi_get_esp_path_for_os (device, esp_path); return g_strdup_printf ("%s/%s%s.efi", base, cmd, suffix); } @@ -219,11 +222,11 @@ fu_uefi_get_esrt_entry_paths (const gchar *esrt_path, GError **error) } gchar * -fu_uefi_get_esp_path_for_os (const gchar *base) +fu_uefi_get_esp_path_for_os (FuDevice *device, const gchar *base) { #ifndef EFI_OS_DIR const gchar *os_release_id = NULL; - const gchar *id_like_id; + const gchar *id_like_id = NULL; g_autofree gchar *esp_path = NULL; g_autoptr(GError) error_local = NULL; g_autoptr(GHashTable) os_release = fwupd_get_os_release (&error_local); @@ -247,6 +250,12 @@ fu_uefi_get_esp_path_for_os (const gchar *base) g_debug ("Using ID_LIKE key from os-release"); return g_steal_pointer (&id_like_path); } + } + /* try to fallback to use UEFI removable path if ID_LIKE path doesn't exist */ + if (fu_device_get_metadata_boolean (device, "FallbacktoRemovablePath")) { + esp_path = g_build_filename (base, "EFI", "boot", NULL); + if (!g_file_test (esp_path, G_FILE_TEST_IS_DIR)) + g_debug ("failed to fallback due to missing %s", esp_path); } return g_steal_pointer (&esp_path); #else diff --git a/plugins/uefi/fu-uefi-common.h b/plugins/uefi/fu-uefi-common.h index 42f89e956..c8842d2ad 100644 --- a/plugins/uefi/fu-uefi-common.h +++ b/plugins/uefi/fu-uefi-common.h @@ -11,6 +11,8 @@ #include "fwupd-common.h" +#include "fu-device.h" + #define EFI_CAPSULE_HEADER_FLAGS_PERSIST_ACROSS_RESET 0x00010000 #define EFI_CAPSULE_HEADER_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define EFI_CAPSULE_HEADER_FLAGS_INITIATE_RESET 0x00040000 @@ -58,7 +60,8 @@ typedef struct __attribute__((__packed__)) { /* the biggest size SPI part currently seen */ #define FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE (32 * 1024 * 1024) -gchar *fu_uefi_get_esp_app_path (const gchar *esp_path, +gchar *fu_uefi_get_esp_app_path (FuDevice *device, + const gchar *esp_path, const gchar *cmd, GError **error); gchar *fu_uefi_get_built_app_path (GError **error); @@ -70,7 +73,8 @@ gboolean fu_uefi_get_bitmap_size (const guint8 *buf, gboolean fu_uefi_get_framebuffer_size (guint32 *width, guint32 *height, GError **error); -gchar *fu_uefi_get_esp_path_for_os (const gchar *esp_path); +gchar *fu_uefi_get_esp_path_for_os (FuDevice *device, + const gchar *esp_path); GPtrArray *fu_uefi_get_esrt_entry_paths (const gchar *esrt_path, GError **error); guint64 fu_uefi_read_file_as_uint64 (const gchar *path, diff --git a/plugins/uefi/fu-uefi-device.c b/plugins/uefi/fu-uefi-device.c index e3608f816..d5179cf31 100644 --- a/plugins/uefi/fu-uefi-device.c +++ b/plugins/uefi/fu-uefi-device.c @@ -560,7 +560,7 @@ fu_uefi_device_write_firmware (FuDevice *device, return FALSE; /* save the blob to the ESP */ - directory = fu_uefi_get_esp_path_for_os (esp_path); + directory = fu_uefi_get_esp_path_for_os (device, esp_path); basename = g_strdup_printf ("fwupd-%s.cap", self->fw_class); fn = g_build_filename (directory, "fw", basename, NULL); if (!fu_common_mkdir_parent (fn, error)) @@ -588,7 +588,7 @@ fu_uefi_device_write_firmware (FuDevice *device, /* some legacy devices use the old name to deduplicate boot entries */ if (fu_device_has_custom_flag (device, "use-legacy-bootmgr-desc")) bootmgr_desc = "Linux-Firmware-Updater"; - if (!fu_uefi_bootmgr_bootnext (esp_path, bootmgr_desc, flags, error)) + if (!fu_uefi_bootmgr_bootnext (device, esp_path, bootmgr_desc, flags, error)) return FALSE; /* success! */ diff --git a/plugins/uefi/uefi.conf b/plugins/uefi/uefi.conf index d9ef4610e..d9775263e 100644 --- a/plugins/uefi/uefi.conf +++ b/plugins/uefi/uefi.conf @@ -10,3 +10,7 @@ # amount of free space required on the ESP, for example using 0x2000000 for 32Mb #RequireESPFreeSpace= + +# with the UEFI removable path enabled, the default esp path is set to /EFI/boot +# the shim EFI binary and presumably this is $ESP/EFI/boot/bootx64.efi +#FallbacktoRemovablePath=false