]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
efi_loader: disk: add EFI_PARTITION_INFO_PROTOCOL support
authorJavier Martinez Canillas <javierm@redhat.com>
Thu, 19 Jun 2025 08:34:01 +0000 (10:34 +0200)
committerIlias Apalodimas <ilias.apalodimas@linaro.org>
Thu, 3 Jul 2025 08:32:49 +0000 (11:32 +0300)
The UEFI 2.10 specification mentions that this protocol shall be installed
along with EFI_BLOCK_IO_PROTOCOL. It provides cached partition information
for MBR and GPT partition types.

This patch just implements support for GPT partition types. The legacy MBR
partition types is only needed for backward compatibility and can be added
as a follow-up if needed, to make it fully compliant with the EFI spec.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
include/part_efi.h
lib/efi_loader/efi_disk.c

index 59b7895b8a2398a822b652ca8f4ac51b8a2a0716..fb402df6f13ec1cf68647b3c37b75e505c7feb9a 100644 (file)
@@ -138,4 +138,24 @@ typedef struct _legacy_mbr {
        __le16 signature;
 } __packed legacy_mbr;
 
+#define EFI_PARTITION_INFO_PROTOCOL_GUID \
+       EFI_GUID(0x8cf2f62c, 0xbc9b, 0x4821, 0x80, \
+                0x8d, 0xec, 0x9e, 0xc4, 0x21, 0xa1, 0xa0)
+
+#define EFI_PARTITION_INFO_PROTOCOL_REVISION 0x0001000
+#define PARTITION_TYPE_OTHER 0x00
+#define PARTITION_TYPE_MBR 0x01
+#define PARTITION_TYPE_GPT 0x02
+
+struct efi_partition_info {
+       u32 revision;
+       u32 type;
+       u8 system;
+       u8 reserved[7];
+       union {
+               struct partition mbr;
+               gpt_entry gpt;
+       } info;
+} __packed;
+
 #endif /* _DISK_PART_EFI_H */
index 47b583cc5e12d2c09117fadadcf3e557b6fc8256..130c4db9606f7f0d74f8911810652ed4b3f0abc2 100644 (file)
@@ -26,6 +26,7 @@ struct efi_system_partition efi_system_partition = {
 
 const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
 const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
+const efi_guid_t efi_partition_info_guid = EFI_PARTITION_INFO_PROTOCOL_GUID;
 
 /**
  * struct efi_disk_obj - EFI disk object
@@ -35,6 +36,7 @@ const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
  * @media:     block I/O media information
  * @dp:                device path to the block device
  * @volume:    simple file system protocol of the partition
+ * @info:      EFI partition info protocol interface
  */
 struct efi_disk_obj {
        struct efi_object header;
@@ -42,6 +44,7 @@ struct efi_disk_obj {
        struct efi_block_io_media media;
        struct efi_device_path *dp;
        struct efi_simple_file_system_protocol *volume;
+       struct efi_partition_info info;
 };
 
 /**
@@ -426,6 +429,7 @@ static efi_status_t efi_disk_add_dev(
        /* Fill in object data */
        if (part_info) {
                struct efi_device_path *node = efi_dp_part_node(desc, part);
+               struct efi_partition_info *info = &diskobj->info;
                struct efi_handler *handler;
                void *protocol_interface;
 
@@ -454,18 +458,48 @@ static efi_status_t efi_disk_add_dev(
                        goto error;
                }
 
+               info->revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
+
+               switch (desc->part_type) {
+#if CONFIG_IS_ENABLED(EFI_PARTITION)
+               case PART_TYPE_EFI:
+                       info->type = PARTITION_TYPE_GPT;
+                       ret = part_get_gpt_pte(desc, part, &info->info.gpt);
+                       if (ret) {
+                               log_debug("get PTE for part %d failed %ld\n",
+                                         part, ret);
+                               goto error;
+                       }
+                       break;
+#endif
+#if CONFIG_IS_ENABLED(DOS_PARTITION)
+               case PART_TYPE_DOS:
+                       info->type = PARTITION_TYPE_MBR;
+
+                       /* TODO: implement support for MBR partition types */
+                       log_debug("EFI_PARTITION_INFO_PROTOCOL doesn't support MBR\n");
+                       break;
+#endif
+               default:
+                       info->type = PARTITION_TYPE_OTHER;
+                       break;
+               }
+
                diskobj->dp = efi_dp_append_node(dp_parent, node);
                efi_free_pool(node);
                diskobj->media.last_block = part_info->size - 1;
-               if (part_info->bootable & PART_EFI_SYSTEM_PARTITION)
+               if (part_info->bootable & PART_EFI_SYSTEM_PARTITION) {
                        esp_guid = &efi_system_partition_guid;
+                       info->system = 1;
+               }
+
        } else {
                diskobj->dp = efi_dp_from_part(desc, part);
                diskobj->media.last_block = desc->lba - 1;
        }
 
        /*
-        * Install the device path and the block IO protocol.
+        * Install the device path, the block IO and partition info protocols.
         *
         * InstallMultipleProtocolInterfaces() checks if the device path is
         * already installed on an other handle and returns EFI_ALREADY_STARTED
@@ -476,6 +510,7 @@ static efi_status_t efi_disk_add_dev(
                                        &handle,
                                        &efi_guid_device_path, diskobj->dp,
                                        &efi_block_io_guid, &diskobj->ops,
+                                       &efi_partition_info_guid, &diskobj->info,
                                        /*
                                         * esp_guid must be last entry as it
                                         * can be NULL. Its interface is NULL.