diff options
-rw-r--r-- | block/partitions/efi.c | 74 | ||||
-rw-r--r-- | block/partitions/efi.h | 3 |
2 files changed, 56 insertions, 21 deletions
diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 1b499dc8fc78..e3cb4f19cf6d 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c | |||
@@ -158,7 +158,7 @@ static inline int pmbr_part_valid(gpt_mbr_record *part) | |||
158 | if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) | 158 | if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) |
159 | goto invalid; | 159 | goto invalid; |
160 | 160 | ||
161 | return 1; | 161 | return GPT_MBR_PROTECTIVE; |
162 | invalid: | 162 | invalid: |
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
@@ -167,21 +167,48 @@ invalid: | |||
167 | * is_pmbr_valid(): test Protective MBR for validity | 167 | * is_pmbr_valid(): test Protective MBR for validity |
168 | * @mbr: pointer to a legacy mbr structure | 168 | * @mbr: pointer to a legacy mbr structure |
169 | * | 169 | * |
170 | * Description: Returns 1 if PMBR is valid, 0 otherwise. | 170 | * Description: Checks for a valid protective or hybrid |
171 | * Validity depends on two things: | 171 | * master boot record (MBR). The validity of a pMBR depends |
172 | * on all of the following properties: | ||
172 | * 1) MSDOS signature is in the last two bytes of the MBR | 173 | * 1) MSDOS signature is in the last two bytes of the MBR |
173 | * 2) One partition of type 0xEE is found | 174 | * 2) One partition of type 0xEE is found |
175 | * | ||
176 | * In addition, a hybrid MBR will have up to three additional | ||
177 | * primary partitions, which point to the same space that's | ||
178 | * marked out by up to three GPT partitions. | ||
179 | * | ||
180 | * Returns 0 upon invalid MBR, or GPT_MBR_PROTECTIVE or | ||
181 | * GPT_MBR_HYBRID depending on the device layout. | ||
174 | */ | 182 | */ |
175 | static int | 183 | static int is_pmbr_valid(legacy_mbr *mbr) |
176 | is_pmbr_valid(legacy_mbr *mbr) | ||
177 | { | 184 | { |
178 | int i; | 185 | int i, ret = 0; /* invalid by default */ |
186 | |||
179 | if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) | 187 | if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) |
180 | return 0; | 188 | goto done; |
189 | |||
190 | for (i = 0; i < 4; i++) { | ||
191 | ret = pmbr_part_valid(&mbr->partition_record[i]); | ||
192 | if (ret == GPT_MBR_PROTECTIVE) { | ||
193 | /* | ||
194 | * Ok, we at least know that there's a protective MBR, | ||
195 | * now check if there are other partition types for | ||
196 | * hybrid MBR. | ||
197 | */ | ||
198 | goto check_hybrid; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | if (ret != GPT_MBR_PROTECTIVE) | ||
203 | goto done; | ||
204 | check_hybrid: | ||
181 | for (i = 0; i < 4; i++) | 205 | for (i = 0; i < 4; i++) |
182 | if (pmbr_part_valid(&mbr->partition_record[i])) | 206 | if ((mbr->partition_record[i].os_type != |
183 | return 1; | 207 | EFI_PMBR_OSTYPE_EFI_GPT) && |
184 | return 0; | 208 | (mbr->partition_record[i].os_type != 0x00)) |
209 | ret = GPT_MBR_HYBRID; | ||
210 | done: | ||
211 | return ret; | ||
185 | } | 212 | } |
186 | 213 | ||
187 | /** | 214 | /** |
@@ -548,17 +575,22 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, | |||
548 | 575 | ||
549 | lastlba = last_lba(state->bdev); | 576 | lastlba = last_lba(state->bdev); |
550 | if (!force_gpt) { | 577 | if (!force_gpt) { |
551 | /* This will be added to the EFI Spec. per Intel after v1.02. */ | 578 | /* This will be added to the EFI Spec. per Intel after v1.02. */ |
552 | legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); | 579 | legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL); |
553 | if (legacymbr) { | 580 | if (!legacymbr) |
554 | read_lba(state, 0, (u8 *) legacymbr, | 581 | goto fail; |
555 | sizeof (*legacymbr)); | 582 | |
556 | good_pmbr = is_pmbr_valid(legacymbr); | 583 | read_lba(state, 0, (u8 *)legacymbr, sizeof(*legacymbr)); |
557 | kfree(legacymbr); | 584 | good_pmbr = is_pmbr_valid(legacymbr); |
558 | } | 585 | kfree(legacymbr); |
559 | if (!good_pmbr) | 586 | |
560 | goto fail; | 587 | if (!good_pmbr) |
561 | } | 588 | goto fail; |
589 | |||
590 | pr_debug("Device has a %s MBR\n", | ||
591 | good_pmbr == GPT_MBR_PROTECTIVE ? | ||
592 | "protective" : "hybrid"); | ||
593 | } | ||
562 | 594 | ||
563 | good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, | 595 | good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, |
564 | &pgpt, &pptes); | 596 | &pgpt, &pptes); |
diff --git a/block/partitions/efi.h b/block/partitions/efi.h index e645ecb35bf3..7fef625c04de 100644 --- a/block/partitions/efi.h +++ b/block/partitions/efi.h | |||
@@ -37,6 +37,9 @@ | |||
37 | #define EFI_PMBR_OSTYPE_EFI 0xEF | 37 | #define EFI_PMBR_OSTYPE_EFI 0xEF |
38 | #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE | 38 | #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE |
39 | 39 | ||
40 | #define GPT_MBR_PROTECTIVE 1 | ||
41 | #define GPT_MBR_HYBRID 2 | ||
42 | |||
40 | #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL | 43 | #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL |
41 | #define GPT_HEADER_REVISION_V1 0x00010000 | 44 | #define GPT_HEADER_REVISION_V1 0x00010000 |
42 | #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 | 45 | #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 |