[PATCH] efi_loader: improve detection of ESP for storing UEFI variables

Paulo Alcantara pc at cjr.nz
Mon Nov 9 00:58:55 CET 2020


The UEFI specification does not restrict on the number and location of
ESPs in a system.  They are discovered as required by looking at the
partition type, but firmware implementations are allowed to support
ESPs which do not contain a valid partition type.

Besides checking for the partition type, for non-removable media check
if /EFI directory exists, otherwise check if /EFI/BOOT/BOOT{ARCH}.EFI
file exists as specified in UEFI 2.8 "13.3.1.3 Directory Structure".

Signed-off-by: Paulo Alcantara (SUSE) <pc at cjr.nz>
---
 lib/efi_loader/efi_disk.c | 60 +++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 22 deletions(-)

diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 7bd1ccec4501..2940a2edf2e8 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -335,6 +335,35 @@ static int efi_fs_exists(struct blk_desc *desc, int part)
 	return 1;
 }
 
+/**
+ * efi_part_is_esp() - check if a partition is an EFI system partition
+ *
+ * @desc:	block device descriptor
+ * @part:	partition number
+ * Return:	true if a partition is an EFI system partition
+ *		false otherwise
+ */
+static bool efi_part_is_esp(struct blk_desc *desc, int part)
+{
+	int ret;
+	struct disk_partition info;
+
+	ret = part_get_info(desc, part, &info);
+	if (ret)
+		return false;
+
+	if (info.bootable & PART_EFI_SYSTEM_PARTITION)
+		return true;
+
+	if (fs_set_blk_dev_with_part(desc, part))
+		return false;
+
+	if (!desc->removable)
+		return !!fs_exists("/EFI");
+
+	return !!fs_exists("/EFI/BOOT/" BOOTEFI_NAME);
+}
+
 /**
  * efi_disk_add_dev() - create a handle for a partition or disk
  *
@@ -436,21 +465,14 @@ static efi_status_t efi_disk_add_dev(
 		*disk = diskobj;
 
 	/* Store first EFI system partition */
-	if (part && !efi_system_partition.if_type) {
-		int r;
-		struct disk_partition info;
-
-		r = part_get_info(desc, part, &info);
-		if (r)
-			return EFI_DEVICE_ERROR;
-		if (info.bootable & PART_EFI_SYSTEM_PARTITION) {
-			efi_system_partition.if_type = desc->if_type;
-			efi_system_partition.devnum = desc->devnum;
-			efi_system_partition.part = part;
-			EFI_PRINT("EFI system partition: %s %d:%d\n",
-				  blk_get_if_type_name(desc->if_type),
-				  desc->devnum, part);
-		}
+	if (part && !efi_system_partition.if_type &&
+	    efi_part_is_esp(desc, part)) {
+		efi_system_partition.if_type = desc->if_type;
+		efi_system_partition.devnum = desc->devnum;
+		efi_system_partition.part = part;
+		EFI_PRINT("EFI system partition: %s %d:%d\n",
+			  blk_get_if_type_name(desc->if_type),
+			  desc->devnum, part);
 	}
 	return EFI_SUCCESS;
 }
@@ -614,9 +636,7 @@ bool efi_disk_is_system_part(efi_handle_t handle)
 {
 	struct efi_handler *handler;
 	struct efi_disk_obj *diskobj;
-	struct disk_partition info;
 	efi_status_t ret;
-	int r;
 
 	/* check if this is a block device */
 	ret = efi_search_protocol(handle, &efi_block_io_guid, &handler);
@@ -625,9 +645,5 @@ bool efi_disk_is_system_part(efi_handle_t handle)
 
 	diskobj = container_of(handle, struct efi_disk_obj, header);
 
-	r = part_get_info(diskobj->desc, diskobj->part, &info);
-	if (r)
-		return false;
-
-	return !!(info.bootable & PART_EFI_SYSTEM_PARTITION);
+	return efi_part_is_esp(diskobj->desc, diskobj->part);
 }
-- 
2.29.2



More information about the U-Boot mailing list