diff options
author | sobomax <sobomax@FreeBSD.org> | 2006-06-26 00:32:54 +0000 |
---|---|---|
committer | sobomax <sobomax@FreeBSD.org> | 2006-06-26 00:32:54 +0000 |
commit | c410e9767338b92aea6653ce3a5fd0b0291e2a8c (patch) | |
tree | 79afb48b764c7a886fb590a241564dda51c30b6b /sys/geom | |
parent | 1d174c9f4d2c265d6959ed3c4e6bf8dca05b1f02 (diff) | |
download | FreeBSD-src-c410e9767338b92aea6653ce3a5fd0b0291e2a8c.zip FreeBSD-src-c410e9767338b92aea6653ce3a5fd0b0291e2a8c.tar.gz |
Improve check for protective MBR. Instead of assiming that protective
MBR should have only one entry of type 0xEE, consider protective MBR
to be one, that has at least one entry of type 0xEE covering the whole
unit. This makes GEOM_GPT compatible with disks partitioned by the
Apple's BootCamp.
Approved in principle by: marcel
MFC After: 1 month
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/geom_gpt.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/sys/geom/geom_gpt.c b/sys/geom/geom_gpt.c index aa074ee..24aa3c9 100644 --- a/sys/geom/geom_gpt.c +++ b/sys/geom/geom_gpt.c @@ -360,31 +360,50 @@ g_gpt_has_pmbr(struct g_consumer *cp, int *error) { char *buf; uint8_t *typ; - int i, pmbr; + int i, pmbr, vmbr; uint16_t magic; + uint32_t dp_start, dp_size; buf = g_read_data(cp, 0L, cp->provider->sectorsize, error); if (buf == NULL) return (0); pmbr = 0; + vmbr = 0; magic = le16toh(*(uint16_t *)(uintptr_t)(buf + DOSMAGICOFFSET)); if (magic != DOSMAGIC) goto out; + /* + * Check that there are at least one partition of type + * DOSPTYP_PMBR that covers the whole unit. + */ for (i = 0; i < 4; i++) { typ = buf + DOSPARTOFF + i * sizeof(struct dos_partition) + offsetof(struct dos_partition, dp_typ); + bcopy(buf + DOSPARTOFF + i * sizeof(struct dos_partition) + + offsetof(struct dos_partition, dp_start), &dp_start, sizeof(dp_start)); + bcopy(buf + DOSPARTOFF + i * sizeof(struct dos_partition) + + offsetof(struct dos_partition, dp_size), &dp_size, sizeof(dp_size)); + if ((*typ == DOSPTYP_PMBR) && + (le32toh(dp_start) == 1) && + (cp->provider->mediasize == + (le32toh(dp_size) * 512ULL))) { + pmbr = 1; + break; + } if (*typ != 0 && *typ != DOSPTYP_PMBR) - goto out; + vmbr = 1; } - pmbr = 1; - out: g_free(buf); - return (pmbr); + /* + * Return true if protective MBR is detected or if MBR has + * no valid entries at all. + */ + return (pmbr || !vmbr); } static void |