summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-06-17 00:27:31 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-06-17 00:27:31 +0000
commit81f9f199b5e2a6741e5a9a68d39dd00dadaa4e18 (patch)
treeaa5797e58e49aa5ab1063818eacfa236c19c2adf /sys/arch/amd64
parent49e31b3e7fe854aae88f968da9911e2a4fd5d878 (diff)
significantly simplified disklabel infrastructure. MBR handling becomes MI
to support hotplug media on most architectures. disklabel setup and verification done using new helper functions. Disklabels must *always* have a correct checksum now. Same code paths are used to learn on-disk location disklabels, to avoid new errors sneaking in. Tested on almost all cases, testing help from todd, kettenis, krw, otto, dlg, robert, gwk, drahn
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/disksubr.c280
-rw-r--r--sys/arch/amd64/include/disklabel.h53
2 files changed, 19 insertions, 314 deletions
diff --git a/sys/arch/amd64/amd64/disksubr.c b/sys/arch/amd64/amd64/disksubr.c
index 437f3674c2e..3dc92c8504f 100644
--- a/sys/arch/amd64/amd64/disksubr.c
+++ b/sys/arch/amd64/amd64/disksubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disksubr.c,v 1.49 2007/06/14 03:37:23 deraadt Exp $ */
+/* $OpenBSD: disksubr.c,v 1.50 2007/06/17 00:27:28 deraadt Exp $ */
/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
/*
@@ -29,16 +29,12 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
-#include <sys/device.h>
#include <sys/disklabel.h>
-#include <sys/syslog.h>
#include <sys/disk.h>
#include <sys/reboot.h>
#include <sys/conf.h>
@@ -69,37 +65,13 @@ char *
readdisklabel(dev_t dev, void (*strat)(struct buf *),
struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly)
{
- struct dos_partition dp[NDOSPART], *dp2;
- struct partition *pp;
- struct disklabel *dlp;
bios_diskinfo_t *pdi;
- unsigned long extoff = 0;
- unsigned int fattest;
struct buf *bp = NULL;
- daddr64_t part_blkno = DOSBBSECTOR;
dev_t devno;
- char *msg = NULL;
- int dospartoff, cyl, i, ourpart = -1;
- int wander = 1, n = 0, loop = 0;
+ char *msg;
- /* minimal requirements for archetypal disk label */
- if (lp->d_secsize < DEV_BSIZE)
- lp->d_secsize = DEV_BSIZE;
- if (DL_GETDSIZE(lp) == 0)
- DL_SETDSIZE(lp, MAXDISKSIZE);
- if (lp->d_secpercyl == 0) {
- msg = "invalid geometry";
+ if ((msg = initdisklabel(lp)))
goto done;
- }
- lp->d_npartitions = RAW_PART + 1;
- for (i = 0; i < RAW_PART; i++) {
- DL_SETPSIZE(&lp->d_partitions[i], 0);
- DL_SETPOFFSET(&lp->d_partitions[i], 0);
- }
- if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
- DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
- DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
- lp->d_version = 1;
/* Look for any BIOS geometry information we should honour. */
devno = chrtoblk(dev);
@@ -124,193 +96,21 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *),
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
- /* do dos partitions in the process of getting disklabel? */
- dospartoff = 0;
- cyl = LABELSECTOR / lp->d_secpercyl;
-
- /*
- * Read dos partition table, follow extended partitions.
- * Map the partitions to disklabel entries i-p
- */
- while (wander && n < 8 && loop < 8) {
- loop++;
- wander = 0;
- if (part_blkno < extoff)
- part_blkno = extoff;
-
- /* read boot record */
- bp->b_blkno = part_blkno;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- bp->b_cylinder = part_blkno / lp->d_secpercyl;
- (*strat)(bp);
-
- /* if successful, wander through dos partition table */
- if (biowait(bp)) {
- msg = "dos partition I/O error";
- goto done;
- }
- bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
-
- if (ourpart == -1 && part_blkno == DOSBBSECTOR) {
- /* Search for our MBR partition */
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
- i++, dp2++)
- if (letoh32(dp2->dp_size) &&
- dp2->dp_typ == DOSPTYP_OPENBSD)
- ourpart = i;
- if (ourpart == -1)
- goto donot;
- /*
- * This is our MBR partition. need sector address
- * for SCSI/IDE, cylinder for ESDI/ST506/RLL
- */
- dp2 = &dp[ourpart];
- dospartoff = letoh32(dp2->dp_start) + part_blkno;
- cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
-
- /* XXX build a temporary disklabel */
- DL_SETPSIZE(&lp->d_partitions[0], letoh32(dp2->dp_size));
- DL_SETPOFFSET(&lp->d_partitions[0],
- letoh32(dp2->dp_start) + part_blkno);
- if (lp->d_ntracks == 0)
- lp->d_ntracks = dp2->dp_ehd + 1;
- if (lp->d_nsectors == 0)
- lp->d_nsectors = DPSECT(dp2->dp_esect);
- if (lp->d_secpercyl == 0)
- lp->d_secpercyl = lp->d_ntracks *
- lp->d_nsectors;
- }
-donot:
- /*
- * In case the disklabel read below fails, we want to
- * provide a fake label in i-p.
- */
- for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
- pp = &lp->d_partitions[8+n];
-
- if (dp2->dp_typ == DOSPTYP_OPENBSD)
- continue;
- if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
- continue;
- if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
- continue;
- if (letoh32(dp2->dp_size) == 0)
- continue;
- if (letoh32(dp2->dp_start))
- DL_SETPOFFSET(pp,
- letoh32(dp2->dp_start) + part_blkno);
-
- DL_SETPSIZE(pp, letoh32(dp2->dp_size));
-
- switch (dp2->dp_typ) {
- case DOSPTYP_UNUSED:
- pp->p_fstype = FS_UNUSED;
- n++;
- break;
-
- case DOSPTYP_LINUX:
- pp->p_fstype = FS_EXT2FS;
- n++;
- break;
-
- case DOSPTYP_FAT12:
- case DOSPTYP_FAT16S:
- case DOSPTYP_FAT16B:
- case DOSPTYP_FAT16L:
- case DOSPTYP_FAT32:
- case DOSPTYP_FAT32L:
- pp->p_fstype = FS_MSDOS;
- n++;
- break;
- case DOSPTYP_EXTEND:
- case DOSPTYP_EXTENDL:
- part_blkno = letoh32(dp2->dp_start) + extoff;
- if (!extoff) {
- extoff = letoh32(dp2->dp_start);
- part_blkno = 0;
- }
- wander = 1;
- break;
- default:
- pp->p_fstype = FS_OTHER;
- n++;
- break;
- }
- }
- }
- lp->d_bbsize = 8192;
- lp->d_sbsize = 64*1024; /* XXX ? */
- lp->d_npartitions = MAXPARTITIONS;
-
- if (n == 0 && part_blkno == DOSBBSECTOR) {
- /* Check for a short jump instruction. */
- fattest = ((bp->b_data[0] << 8) & 0xff00) | (bp->b_data[2] &
- 0xff);
- if (fattest != 0xeb90 && fattest != 0xe900)
- goto notfat;
-
- /* Check for a valid bytes per sector value. */
- fattest = ((bp->b_data[12] << 8) & 0xff00) | (bp->b_data[11] &
- 0xff);
- if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
- goto notfat;
-
- /* Check the end of sector marker. */
- fattest = ((bp->b_data[510] << 8) & 0xff00) | (bp->b_data[511] &
- 0xff);
- if (fattest != 0x55aa)
- goto notfat;
-
- /* Looks like a FAT filesystem. Spoof 'i'. */
- DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
- DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
- DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
- lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
- }
-notfat:
-
- /* don't read the on-disk label if we are in spoofed-only mode */
- if (spoofonly)
- goto done;
-
- /* next, dig out disk label */
- bp->b_blkno = dospartoff + LABELSECTOR;
- bp->b_cylinder = cyl;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- (*strat)(bp);
-
- /* if successful, locate disk label within block and validate */
- if (biowait(bp)) {
- /* XXX we return the faked label built so far */
- msg = "disk label I/O error";
+ msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly);
+ if (msg == NULL)
goto done;
- }
- for (dlp = (struct disklabel *)bp->b_data;
- dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
- dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
- if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
- if (msg == NULL)
- msg = "no disk label";
- } else if (dlp->d_npartitions > MAXPARTITIONS ||
- dkcksum(dlp) != 0)
- msg = "disk label corrupted";
- else {
- DL_SETDSIZE(dlp, DL_GETDSIZE(lp));
- *lp = *dlp;
- msg = NULL;
- break;
- }
- }
#if defined(CD9660)
- if (msg && iso_disklabelspoof(dev, strat, lp) == 0)
+ if (iso_disklabelspoof(dev, strat, lp) == 0) {
msg = NULL;
+ goto done;
+ }
#endif
#if defined(UDF)
- if (msg && udf_disklabelspoof(dev, strat, lp) == 0)
+ if (udf_disklabelspoof(dev, strat, lp) == 0) {
msg = NULL;
+ goto done;
+ }
#endif
done:
@@ -318,7 +118,6 @@ done:
bp->b_flags |= B_INVAL;
brelse(bp);
}
- disklabeltokernlabel(lp);
return (msg);
}
@@ -330,73 +129,30 @@ int
writedisklabel(dev_t dev, void (*strat)(struct buf *),
struct disklabel *lp, struct cpu_disklabel *osdep)
{
- struct dos_partition dp[NDOSPART], *dp2;
+ int error, partoff = -1, cyl = 0;
struct disklabel *dlp;
struct buf *bp = NULL;
- int error, dospartoff, cyl, i;
- int ourpart = -1;
/* get a buffer and initialize it */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
- /* do dos partitions in the process of getting disklabel? */
- dospartoff = 0;
- cyl = LABELSECTOR / lp->d_secpercyl;
-
- /* read master boot record */
- bp->b_blkno = DOSBBSECTOR;
- bp->b_bcount = lp->d_secsize;
- bp->b_flags = B_BUSY | B_READ;
- bp->b_cylinder = DOSBBSECTOR / lp->d_secpercyl;
- (*strat)(bp);
-
- if ((error = biowait(bp)) != 0)
+ if (readdoslabel(bp, strat, lp, osdep, &partoff, &cyl, 1) != NULL) {
+ error = EIO;
goto done;
-
- /* XXX how do we check veracity/bounds of this? */
- bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp));
-
- for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
- if (letoh32(dp2->dp_size) && dp2->dp_typ == DOSPTYP_OPENBSD)
- ourpart = i;
-
- if (ourpart != -1) {
- dp2 = &dp[ourpart];
-
- /*
- * need sector address for SCSI/IDE,
- * cylinder for ESDI/ST506/RLL
- */
- dospartoff = letoh32(dp2->dp_start);
- cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
}
- /* next, dig out disk label */
- bp->b_blkno = dospartoff + LABELSECTOR;
+ /* Read it in, slap the new label in, and write it back out */
+ bp->b_blkno = partoff + LABELSECTOR;
bp->b_cylinder = cyl;
bp->b_bcount = lp->d_secsize;
bp->b_flags = B_BUSY | B_READ;
(*strat)(bp);
-
- /* if successful, locate disk label within block and validate */
if ((error = biowait(bp)) != 0)
goto done;
- for (dlp = (struct disklabel *)bp->b_data;
- dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
- dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
- if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
- dkcksum(dlp) == 0) {
- *dlp = *lp;
- bp->b_flags = B_BUSY | B_WRITE;
- (*strat)(bp);
- error = biowait(bp);
- goto done;
- }
- }
- /* Write it in the regular place. */
- *(struct disklabel *)bp->b_data = *lp;
+ dlp = (struct disklabel *)(bp->b_data + LABELOFFSET);
+ *dlp = *lp;
bp->b_flags = B_BUSY | B_WRITE;
(*strat)(bp);
error = biowait(bp);
diff --git a/sys/arch/amd64/include/disklabel.h b/sys/arch/amd64/include/disklabel.h
index 0851f8a57b9..12c78faa294 100644
--- a/sys/arch/amd64/include/disklabel.h
+++ b/sys/arch/amd64/include/disklabel.h
@@ -1,5 +1,4 @@
-/* $OpenBSD: disklabel.h,v 1.8 2006/10/20 23:47:42 krw Exp $ */
-/* $NetBSD: disklabel.h,v 1.3 1996/03/09 20:52:54 ghudson Exp $ */
+/* $OpenBSD: disklabel.h,v 1.9 2007/06/17 00:27:26 deraadt Exp $ */
/*
* Copyright (c) 1994 Christopher G. Demetriou
@@ -37,58 +36,8 @@
#define LABELSECTOR 1 /* sector containing label */
#define LABELOFFSET 0 /* offset of label in sector */
#define MAXPARTITIONS 16 /* number of partitions */
-#define RAW_PART 2 /* raw partition: ie. rsd0c */
-
-/* DOS partition table -- located in boot block */
-#define DOSBBSECTOR 0 /* DOS boot block relative sector # */
-#define DOSPARTOFF 446
-#define DOSDISKOFF 444
-#define NDOSPART 4
-#define DOSACTIVE 0x80 /* active partition */
-
-struct dos_partition {
- u_int8_t dp_flag; /* bootstrap flags */
- u_int8_t dp_shd; /* starting head */
- u_int8_t dp_ssect; /* starting sector */
- u_int8_t dp_scyl; /* starting cylinder */
- u_int8_t dp_typ; /* partition type (see below) */
- u_int8_t dp_ehd; /* end head */
- u_int8_t dp_esect; /* end sector */
- u_int8_t dp_ecyl; /* end cylinder */
- u_int32_t dp_start; /* absolute starting sector number */
- u_int32_t dp_size; /* partition size in sectors */
-};
-
-/* Known DOS partition types. */
-#define DOSPTYP_UNUSED 0x00 /* Unused partition */
-#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */
-#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */
-#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */
-#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */
-#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */
-#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */
-#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */
-#define DOSPTYP_EXTENDL 0x0f /* Extended, LBA-mapped; contains sub-partitions */
-#define DOSPTYP_ONTRACK 0x54
-#define DOSPTYP_LINUX 0x83 /* That other thing */
-#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */
-#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */
-#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */
-
-struct dos_mbr {
- u_int8_t dmbr_boot[DOSPARTOFF];
- struct dos_partition dmbr_parts[NDOSPART];
- u_int16_t dmbr_sign;
-} __packed;
-
-#define DOSMBR_SIGNATURE (0xaa55)
-#define DOSMBR_SIGNATURE_OFF (0x1fe)
struct cpu_disklabel {
};
-/* Isolate the relevant bits to get sector and cylinder. */
-#define DPSECT(s) ((s) & 0x3f)
-#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2))
-
#endif /* _MACHINE_DISKLABEL_H_ */