diff options
author | marcel <marcel@FreeBSD.org> | 2008-02-29 22:41:36 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2008-02-29 22:41:36 +0000 |
commit | 1c97028d69164abca37a0f85c3ec780c5415b654 (patch) | |
tree | ecc21a09e37b4cc8bb63283880421d8f47c69375 /sys | |
parent | a7d75a1a2ac7d7261da0c882d56c0854fe9cd364 (diff) | |
download | FreeBSD-src-1c97028d69164abca37a0f85c3ec780c5415b654.zip FreeBSD-src-1c97028d69164abca37a0f85c3ec780c5415b654.tar.gz |
Follow-up improvements to the handling of false positives: If the
partition table is empty, check to see if we have something that
looks sufficiently like a BPB. On non-i386 machines, the boot
sector typically doesn't contain boot code; the end of the boot
sector is all zeroes. This is also where the partition table is
for MBRs.
We only check the sector size and cluster size, as that seems to
be the most reliable across implementations, BPB versions and
platforms.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/part/g_part_mbr.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index 9e6b56e..c12bf24 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -118,6 +118,24 @@ mbr_parse_type(const char *type, u_char *dp_typ) return (EINVAL); } +static int +mbr_probe_bpb(u_char *bpb) +{ + uint16_t secsz; + uint8_t clstsz; + +#define PO2(x) ((x & (x - 1)) == 0) + secsz = le16dec(bpb); + if (secsz < 512 || secsz > 4096 || !PO2(secsz)) + return (0); + clstsz = bpb[2]; + if (clstsz < 1 || clstsz > 128 || !PO2(clstsz)) + return (0); +#undef PO2 + + return (1); +} + static void mbr_set_chs(struct g_part_table *table, uint32_t lba, u_char *cylp, u_char *hdp, u_char *secp) @@ -253,7 +271,7 @@ g_part_mbr_probe(struct g_part_table *table, struct g_consumer *cp) { struct g_provider *pp; u_char *buf, *p; - int error, index, res; + int error, index, res, sum; uint16_t magic; pp = cp->provider; @@ -282,8 +300,19 @@ g_part_mbr_probe(struct g_part_table *table, struct g_consumer *cp) goto out; } - /* Match. */ - res = G_PART_PROBE_PRI_NORM; + /* + * If the partition table does not consist of all zeroes, + * assume we have a MBR. If it's all zeroes, we could have + * a boot sector. For example, a boot sector that doesn't + * have boot code -- common on non-i386 hardware. In that + * case we check if we have a possible BPB. If so, then we + * assume we have a boot sector instead. + */ + sum = 0; + for (index = 0; index < NDOSPART * DOSPARTSIZE; index++) + sum += buf[DOSPARTOFF + index]; + if (sum != 0 || !mbr_probe_bpb(buf + 0x0b)) + res = G_PART_PROBE_PRI_NORM; out: g_free(buf); |