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) <p...@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

Reply via email to