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.
This commit is contained in:
Hsieh-Tseng Shen 2020-11-05 09:22:09 +08:00 committed by Mario Limonciello
parent cceeb75c7b
commit b47eee9a8a
7 changed files with 54 additions and 17 deletions

View File

@ -241,7 +241,7 @@ fu_plugin_uefi_write_splash_data (FuPlugin *plugin,
/* save to a predicatable filename */ /* save to a predicatable filename */
esp_path = fu_volume_get_mount_point (data->esp); 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); basename = g_strdup_printf ("fwupd-%s.cap", FU_EFIVAR_GUID_UX_CAPSULE);
fn = g_build_filename (directory, "fw", basename, NULL); fn = g_build_filename (directory, "fw", basename, NULL);
if (!fu_common_mkdir_parent (fn, error)) if (!fu_common_mkdir_parent (fn, error))
@ -425,6 +425,7 @@ static void
fu_plugin_uefi_load_config (FuPlugin *plugin, FuDevice *device) fu_plugin_uefi_load_config (FuPlugin *plugin, FuDevice *device)
{ {
gboolean disable_shim; gboolean disable_shim;
gboolean fallback_removable_path;
guint64 sz_reqd = FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE; guint64 sz_reqd = FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE;
g_autofree gchar *require_esp_free_space = NULL; 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, fu_device_set_metadata_boolean (device,
"RequireShimForSecureBoot", "RequireShimForSecureBoot",
!disable_shim); !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 static void

View File

@ -239,10 +239,11 @@ fu_uefi_copy_asset (const gchar *source, const gchar *target, GError **error)
} }
gboolean gboolean
fu_uefi_bootmgr_bootnext (const gchar *esp_path, fu_uefi_bootmgr_bootnext (FuDevice *device,
const gchar *description, const gchar *esp_path,
FuUefiBootmgrFlags flags, const gchar *description,
GError **error) FuUefiBootmgrFlags flags,
GError **error)
{ {
const gchar *filepath; const gchar *filepath;
gboolean use_fwup_path = TRUE; gboolean use_fwup_path = TRUE;
@ -273,14 +274,23 @@ fu_uefi_bootmgr_bootnext (const gchar *esp_path,
secure_boot = fu_efivar_secure_boot_enabled (); secure_boot = fu_efivar_secure_boot_enabled ();
if (secure_boot) { if (secure_boot) {
/* test to make sure shim is there if we need it */ /* 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) if (shim_app == NULL)
return FALSE; 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)) { if (g_file_test (shim_app, G_FILE_TEST_EXISTS)) {
/* use a custom copy of shim for firmware updates */ /* use a custom copy of shim for firmware updates */
if (flags & FU_UEFI_BOOTMGR_FLAG_USE_SHIM_UNIQUE) { 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) if (shim_cpy == NULL)
return FALSE; return FALSE;
if (!fu_uefi_cmp_asset (shim_app, shim_cpy)) { 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 */ /* 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) if (target_app == NULL)
return FALSE; return FALSE;
if (!fu_uefi_cmp_asset (source_app, target_app)) { if (!fu_uefi_cmp_asset (source_app, target_app)) {

View File

@ -10,6 +10,8 @@
#include <glib.h> #include <glib.h>
#include <efivar.h> #include <efivar.h>
#include "fu-device.h"
typedef enum { typedef enum {
FU_UEFI_BOOTMGR_FLAG_NONE = 0, FU_UEFI_BOOTMGR_FLAG_NONE = 0,
FU_UEFI_BOOTMGR_FLAG_USE_SHIM_FOR_SB = 1 << 0, FU_UEFI_BOOTMGR_FLAG_USE_SHIM_FOR_SB = 1 << 0,
@ -17,7 +19,8 @@ typedef enum {
FU_UEFI_BOOTMGR_FLAG_LAST FU_UEFI_BOOTMGR_FLAG_LAST
} FuUefiBootmgrFlags; } FuUefiBootmgrFlags;
gboolean fu_uefi_bootmgr_bootnext (const gchar *esp_path, gboolean fu_uefi_bootmgr_bootnext (FuDevice *device,
const gchar *esp_path,
const gchar *description, const gchar *description,
FuUefiBootmgrFlags flags, FuUefiBootmgrFlags flags,
GError **error); GError **error);

View File

@ -61,13 +61,16 @@ fu_uefi_bootmgr_get_suffix (GError **error)
} }
gchar * 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); const gchar *suffix = fu_uefi_bootmgr_get_suffix (error);
g_autofree gchar *base = NULL; g_autofree gchar *base = NULL;
if (suffix == NULL) if (suffix == NULL)
return 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); 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 * 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 #ifndef EFI_OS_DIR
const gchar *os_release_id = NULL; const gchar *os_release_id = NULL;
const gchar *id_like_id; const gchar *id_like_id = NULL;
g_autofree gchar *esp_path = NULL; g_autofree gchar *esp_path = NULL;
g_autoptr(GError) error_local = NULL; g_autoptr(GError) error_local = NULL;
g_autoptr(GHashTable) os_release = fwupd_get_os_release (&error_local); 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"); g_debug ("Using ID_LIKE key from os-release");
return g_steal_pointer (&id_like_path); 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); return g_steal_pointer (&esp_path);
#else #else

View File

@ -11,6 +11,8 @@
#include "fwupd-common.h" #include "fwupd-common.h"
#include "fu-device.h"
#define EFI_CAPSULE_HEADER_FLAGS_PERSIST_ACROSS_RESET 0x00010000 #define EFI_CAPSULE_HEADER_FLAGS_PERSIST_ACROSS_RESET 0x00010000
#define EFI_CAPSULE_HEADER_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define EFI_CAPSULE_HEADER_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000
#define EFI_CAPSULE_HEADER_FLAGS_INITIATE_RESET 0x00040000 #define EFI_CAPSULE_HEADER_FLAGS_INITIATE_RESET 0x00040000
@ -58,7 +60,8 @@ typedef struct __attribute__((__packed__)) {
/* the biggest size SPI part currently seen */ /* the biggest size SPI part currently seen */
#define FU_UEFI_COMMON_REQUIRED_ESP_FREE_SPACE (32 * 1024 * 1024) #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, const gchar *cmd,
GError **error); GError **error);
gchar *fu_uefi_get_built_app_path (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, gboolean fu_uefi_get_framebuffer_size (guint32 *width,
guint32 *height, guint32 *height,
GError **error); 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, GPtrArray *fu_uefi_get_esrt_entry_paths (const gchar *esrt_path,
GError **error); GError **error);
guint64 fu_uefi_read_file_as_uint64 (const gchar *path, guint64 fu_uefi_read_file_as_uint64 (const gchar *path,

View File

@ -560,7 +560,7 @@ fu_uefi_device_write_firmware (FuDevice *device,
return FALSE; return FALSE;
/* save the blob to the ESP */ /* 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); basename = g_strdup_printf ("fwupd-%s.cap", self->fw_class);
fn = g_build_filename (directory, "fw", basename, NULL); fn = g_build_filename (directory, "fw", basename, NULL);
if (!fu_common_mkdir_parent (fn, error)) 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 */ /* some legacy devices use the old name to deduplicate boot entries */
if (fu_device_has_custom_flag (device, "use-legacy-bootmgr-desc")) if (fu_device_has_custom_flag (device, "use-legacy-bootmgr-desc"))
bootmgr_desc = "Linux-Firmware-Updater"; 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; return FALSE;
/* success! */ /* success! */

View File

@ -10,3 +10,7 @@
# amount of free space required on the ESP, for example using 0x2000000 for 32Mb # amount of free space required on the ESP, for example using 0x2000000 for 32Mb
#RequireESPFreeSpace= #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