aboutsummaryrefslogtreecommitdiffstats
path: root/block/partitions
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr@hp.com>2013-09-11 17:24:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:16 -0400
commitb05ebbbbeb67a420d06567c6b9618a9e644d6104 (patch)
treec8191dab1a7a18752afbb4158e1ad988fbfc0779 /block/partitions
parent3e69ac344007bec5e3987ac86619e140fbc79b72 (diff)
partitions/efi: detect hybrid MBRs
One of the biggest problems with GPT is compatibility with older, non-GPT systems. The problem is addressed by creating hybrid mbrs, an extension, or variant, of the traditional protective mbr. This contains, apart from the 0xEE partition, up three additional primary partitions that point to the same space marked by up to three GPT partitions. The result is that legacy OSs can see the three required MBR partitions and at the same time ignore the GPT-aware partitions that protect the GPT structures. While hybrid MBRs are hacks, workarounds and simply not part of the GPT standard, they do exist and we have no way around them. For instance, by default, OSX creates a hybrid scheme when using multi-OS booting. In order for Linux to properly discover protective MBRs, it must be made aware of devices that have hybrid MBRs. No functionality is changed by this patch, just a debug message informing the user of the MBR scheme that is being used. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Davidlohr Bueso <davidlohr@hp.com> Reviewed-by: Karel Zak <kzak@redhat.com> Acked-by: Matt Fleming <matt.fleming@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'block/partitions')
-rw-r--r--block/partitions/efi.c74
-rw-r--r--block/partitions/efi.h3
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;
162invalid: 162invalid:
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 */
175static int 183static int is_pmbr_valid(legacy_mbr *mbr)
176is_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;
204check_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;
210done:
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