efi: take size of partition entry from GPT header
Subsystems (3)
PATCH v4 1/1 efi: take size of partition entry from GPT header
Use gpt_header.sizeof_partition_entry instead of sizeof(gpt_entry) for GPT entry size.
According to UEFI 2.7 spec 5.3.1 "GPT overview":, the size of a GUID Partition Entry element is defined in the Size Of Partition Entry field of GPT header. The GPT with entries sized more than sizeof(gpt_entry) is not illegal. OVMF firmware from EDK2 perfectly works with it, see edk2-tianocore source code.
Changes since v1: refactoring (extract get_gpt_entry function),
fix (&ptes[i] -> pte)
Changes since v2: use le32_to_cpu, fix typo, sanity check for
sizeof_partition_entry
Changes since v3: style fixes
Signed-off-by Eugene Korenevsky <[email protected]>
--- block/partitions/efi.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-)
block/partitions/efi.c +20 -11
@@ -429,8 +429,8 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, goto fail; }/* Check that sizeof_partition_entry has the correct value */ -if (le32_to_cpu ((*gpt)->sizeof_partition_entry) !=sizeof (gpt_entry)) { -pr_debug ("GUID Partition Entry Size check failed.\n" ); +if (le32_to_cpu ((*gpt)->sizeof_partition_entry) <sizeof (gpt_entry)) { +pr_debug ("GUID Partition Entry Size is too small.\n" ); goto fail; }
@@ -670,6 +670,12 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,return 0 ; } +static gpt_entry *get_gpt_entry (gpt_header *gpt,gpt_entry *ptes,u32 index) +{ +return (gpt_entry *)((u8 *)ptes + +le32_to_cpu (gpt->sizeof_partition_entry) * index); +} +/** * efi_partition(struct parsed_partitions *state) * @state: disk parsed partitions
@@ -704,32 +710,35 @@ int efi_partition(struct parsed_partitions *state)pr_debug ("GUID Partition Table is valid! Yea!\n" ); -for (i =0 ; i <le32_to_cpu (gpt->num_partition_entries) && i < state->limit-1 ; i++) { +for (i =0 ; i <le32_to_cpu (gpt->num_partition_entries) && + i < state->limit-1 ; i++) { +gpt_entry *pte =get_gpt_entry (gpt, ptes, i);struct partition_meta_info *info;unsigned label_count =0 ;unsigned label_max; -u64 start =le64_to_cpu (ptes[i].starting_lba); -u64 size =le64_to_cpu (ptes[i].ending_lba) - -le64_to_cpu (ptes[i].starting_lba) +1ULL ; +u64 start =le64_to_cpu (pte->starting_lba); +u64 size =le64_to_cpu (pte->ending_lba) - +le64_to_cpu (pte->starting_lba) +1ULL ; -if (!is_pte_valid (&ptes[i],last_lba (state->bdev))) +if (!is_pte_valid (pte,last_lba (state->bdev)))continue ;put_partition (state, i+1 , start * ssz, size * ssz);/* If this is a RAID volume, tell md */ -if (!efi_guidcmp (ptes[i].partition_type_guid,PARTITION_LINUX_RAID_GUID )) +if (!efi_guidcmp (pte->partition_type_guid, +PARTITION_LINUX_RAID_GUID )) state->parts[i +1 ].flags =ADDPART_FLAG_RAID ; info = &state->parts[i +1 ].info; -efi_guid_to_str (&ptes[i].unique_partition_guid, info->uuid); +efi_guid_to_str (&pte->unique_partition_guid, info->uuid);/* Naively convert UTF16-LE to 7 bits. */ label_max =min (ARRAY_SIZE (info->volname) -1 , -ARRAY_SIZE (ptes[i].partition_name)); +ARRAY_SIZE (pte->partition_name)); info->volname[label_max] =0 ;while (label_count < label_max) { -u8 c = ptes[i].partition_name[label_count] &0xff ; +u8 c = pte->partition_name[label_count] &0xff ;if (c && !isprint (c)) c ='!' ; info->volname[label_count] = c;
Signature · 1 line
2.18.0