Prev: [PATCH RFC (alt)] efi: add efi_partition_walk and expose for kernel access
Next: [PATCH] tc6393xb: fix wrong goto labels for error handling
From: Will Drewry on 2 Aug 2010 23:00 EFI's GPT partitioning scheme expects that all partitions have a unique identifiers. After initial partition scanning, this information is completely lost to the rest of the kernel. efi_partition_by_guid exposes GPT parsing support in a limited fashion to allow other portions of the kernel to map a partition from GUID to map. This change is motivated the desire to have the ability to specify a UUID argument to a device mapper target allowing it to select the device by the UUID. Change against Linus's tree: 9fe6206f400646a2322096b56c59891d530e8d51 Signed-off-by: Will Drewry <wad(a)chromium.org> v2: pr_debug(KERN_WARNING -> pr_debug(. joe(a)perches.com moved down trailing {. davem(a)davemloft.net --- fs/partitions/efi.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 5 ++++ 2 files changed, 66 insertions(+), 0 deletions(-) diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 9efb2cf..8669c4f 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c @@ -633,3 +633,64 @@ int efi_partition(struct parsed_partitions *state) printk("\n"); return 1; } + +/** + * efi_partition_by_guid + * @bdev: Whole block device to scan for a GPT. + * @guid: Unique identifier for the partition to find. + * + * N.b., returns on the first match since it should be unique. + * + * Returns: + * -1 if an error occurred + * 0 if there was no match (or not GPT) + * >=1 is the index of the partition found. + * + */ +int efi_partition_by_guid(struct block_device *bdev, efi_guid_t *guid) { + gpt_header *gpt = NULL; + gpt_entry *ptes = NULL; + u32 i; + struct parsed_partitions *state; + int part = 0; + + if (!bdev || !guid) + return -1; + + state = kzalloc(sizeof(struct parsed_partitions), GFP_KERNEL); + if (!state) + return -1; + + state->limit = disk_max_parts(bdev->bd_disk); + pr_debug("efi_find_partition looking for gpt\n"); + + state->bdev = bdev; + if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { + pr_debug("efi_find_partition no GPT\n"); + kfree(gpt); + kfree(ptes); + kfree(state); + return 0; + } + + pr_debug("GUID Partition Table is valid! Yea!\n"); + pr_debug("efi_find_partition: 0 -> %d (limit:%d)\n", + le32_to_cpu(gpt->num_partition_entries), + state->limit); + for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && + i < state->limit-1; i++) { + if (!is_pte_valid(&ptes[i], last_lba(bdev))) + continue; + + /* Bails on first hit so duped "unique" GUIDs will be FCFS. */ + if (!efi_guidcmp(ptes[i].unique_partition_guid, + *guid)) { + part = i + 1; + break; + } + } + kfree(ptes); + kfree(gpt); + kfree(state); + return part; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index fb737bc..1a77259 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -301,6 +301,11 @@ extern unsigned long efi_get_time(void); extern int efi_set_rtc_mmss(unsigned long nowtime); extern struct efi_memory_map memmap; +#ifdef CONFIG_EFI_PARTITION +struct block_device; +extern int efi_partition_by_guid(struct block_device *bdev, efi_guid_t *guid); +#endif + /** * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ |