diff options
Diffstat (limited to 'fs/partitions/efi.c')
| -rw-r--r-- | fs/partitions/efi.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c index 038a6022152f..49cfd5f54238 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /************************************************************ | 1 | /************************************************************ |
| 2 | * EFI GUID Partition Table handling | 2 | * EFI GUID Partition Table handling |
| 3 | * Per Intel EFI Specification v1.02 | 3 | * |
| 4 | * http://developer.intel.com/technology/efi/efi.htm | 4 | * http://www.uefi.org/specs/ |
| 5 | * http://www.intel.com/technology/efi/ | ||
| 6 | * | ||
| 5 | * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com> | 7 | * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com> |
| 6 | * Copyright 2000,2001,2002,2004 Dell Inc. | 8 | * Copyright 2000,2001,2002,2004 Dell Inc. |
| 7 | * | 9 | * |
| @@ -92,6 +94,7 @@ | |||
| 92 | * | 94 | * |
| 93 | ************************************************************/ | 95 | ************************************************************/ |
| 94 | #include <linux/crc32.h> | 96 | #include <linux/crc32.h> |
| 97 | #include <linux/math64.h> | ||
| 95 | #include "check.h" | 98 | #include "check.h" |
| 96 | #include "efi.h" | 99 | #include "efi.h" |
| 97 | 100 | ||
| @@ -141,7 +144,8 @@ last_lba(struct block_device *bdev) | |||
| 141 | { | 144 | { |
| 142 | if (!bdev || !bdev->bd_inode) | 145 | if (!bdev || !bdev->bd_inode) |
| 143 | return 0; | 146 | return 0; |
| 144 | return (bdev->bd_inode->i_size >> 9) - 1ULL; | 147 | return div_u64(bdev->bd_inode->i_size, |
| 148 | bdev_logical_block_size(bdev)) - 1ULL; | ||
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | static inline int | 151 | static inline int |
| @@ -188,6 +192,7 @@ static size_t | |||
| 188 | read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) | 192 | read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) |
| 189 | { | 193 | { |
| 190 | size_t totalreadcount = 0; | 194 | size_t totalreadcount = 0; |
| 195 | sector_t n = lba * (bdev_logical_block_size(bdev) / 512); | ||
| 191 | 196 | ||
| 192 | if (!bdev || !buffer || lba > last_lba(bdev)) | 197 | if (!bdev || !buffer || lba > last_lba(bdev)) |
| 193 | return 0; | 198 | return 0; |
| @@ -195,7 +200,7 @@ read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) | |||
| 195 | while (count) { | 200 | while (count) { |
| 196 | int copied = 512; | 201 | int copied = 512; |
| 197 | Sector sect; | 202 | Sector sect; |
| 198 | unsigned char *data = read_dev_sector(bdev, lba++, §); | 203 | unsigned char *data = read_dev_sector(bdev, n++, §); |
| 199 | if (!data) | 204 | if (!data) |
| 200 | break; | 205 | break; |
| 201 | if (copied > count) | 206 | if (copied > count) |
| @@ -257,15 +262,16 @@ static gpt_header * | |||
| 257 | alloc_read_gpt_header(struct block_device *bdev, u64 lba) | 262 | alloc_read_gpt_header(struct block_device *bdev, u64 lba) |
| 258 | { | 263 | { |
| 259 | gpt_header *gpt; | 264 | gpt_header *gpt; |
| 265 | unsigned ssz = bdev_logical_block_size(bdev); | ||
| 266 | |||
| 260 | if (!bdev) | 267 | if (!bdev) |
| 261 | return NULL; | 268 | return NULL; |
| 262 | 269 | ||
| 263 | gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL); | 270 | gpt = kzalloc(ssz, GFP_KERNEL); |
| 264 | if (!gpt) | 271 | if (!gpt) |
| 265 | return NULL; | 272 | return NULL; |
| 266 | 273 | ||
| 267 | if (read_lba(bdev, lba, (u8 *) gpt, | 274 | if (read_lba(bdev, lba, (u8 *) gpt, ssz) < ssz) { |
| 268 | sizeof (gpt_header)) < sizeof (gpt_header)) { | ||
| 269 | kfree(gpt); | 275 | kfree(gpt); |
| 270 | gpt=NULL; | 276 | gpt=NULL; |
| 271 | return NULL; | 277 | return NULL; |
| @@ -601,6 +607,7 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 601 | gpt_header *gpt = NULL; | 607 | gpt_header *gpt = NULL; |
| 602 | gpt_entry *ptes = NULL; | 608 | gpt_entry *ptes = NULL; |
| 603 | u32 i; | 609 | u32 i; |
| 610 | unsigned ssz = bdev_logical_block_size(bdev) / 512; | ||
| 604 | 611 | ||
| 605 | if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { | 612 | if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { |
| 606 | kfree(gpt); | 613 | kfree(gpt); |
| @@ -611,13 +618,14 @@ efi_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
| 611 | pr_debug("GUID Partition Table is valid! Yea!\n"); | 618 | pr_debug("GUID Partition Table is valid! Yea!\n"); |
| 612 | 619 | ||
| 613 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { | 620 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { |
| 621 | u64 start = le64_to_cpu(ptes[i].starting_lba); | ||
| 622 | u64 size = le64_to_cpu(ptes[i].ending_lba) - | ||
| 623 | le64_to_cpu(ptes[i].starting_lba) + 1ULL; | ||
| 624 | |||
| 614 | if (!is_pte_valid(&ptes[i], last_lba(bdev))) | 625 | if (!is_pte_valid(&ptes[i], last_lba(bdev))) |
| 615 | continue; | 626 | continue; |
| 616 | 627 | ||
| 617 | put_partition(state, i+1, le64_to_cpu(ptes[i].starting_lba), | 628 | put_partition(state, i+1, start * ssz, size * ssz); |
| 618 | (le64_to_cpu(ptes[i].ending_lba) - | ||
| 619 | le64_to_cpu(ptes[i].starting_lba) + | ||
| 620 | 1ULL)); | ||
| 621 | 629 | ||
| 622 | /* If this is a RAID volume, tell md */ | 630 | /* If this is a RAID volume, tell md */ |
| 623 | if (!efi_guidcmp(ptes[i].partition_type_guid, | 631 | if (!efi_guidcmp(ptes[i].partition_type_guid, |
