diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-06-17 00:27:31 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-06-17 00:27:31 +0000 |
commit | 81f9f199b5e2a6741e5a9a68d39dd00dadaa4e18 (patch) | |
tree | aa5797e58e49aa5ab1063818eacfa236c19c2adf | |
parent | 49e31b3e7fe854aae88f968da9911e2a4fd5d878 (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
45 files changed, 1392 insertions, 4737 deletions
diff --git a/sys/arch/alpha/alpha/disksubr.c b/sys/arch/alpha/alpha/disksubr.c index 6a7ef3615d3..0f0648ca81e 100644 --- a/sys/arch/alpha/alpha/disksubr.c +++ b/sys/arch/alpha/alpha/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.87 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.88 2007/06/17 00:27:28 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* @@ -30,80 +30,14 @@ * 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> -char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int, - int, struct disklabel *, int); -char *readdoslabel(struct buf *, void (*)(struct buf *), - struct disklabel *, struct cpu_disklabel *, int *, int *, int); - -/* - * Try to read a standard BSD disklabel at a certain sector. - */ -char * -readbsdlabel(struct buf *bp, void (*strat)(struct buf *), - int cyl, int sec, int off, struct disklabel *lp, int spoofonly) -{ - struct disklabel *dlp; - char *msg = NULL; - u_int16_t cksum; - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) - return (NULL); - - bp->b_blkno = sec; - 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"; - return (msg); - } - - /* - * If off is negative, search until the end of the sector for - * the label, otherwise, just look at the specific location - * we're given. - */ - dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0)); - do { - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - if (msg == NULL) - msg = "no disk label"; - } else { - cksum = dkcksum(dlp); - if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) { - msg = "disk label corrupted"; - } else { - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; - msg = NULL; - break; - } - } - if (off >= 0) - break; - dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t)); - } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - - sizeof(*dlp))); - return (msg); -} - /* * Attempt to read a disk label from a device * using the indicated strategy routine. @@ -119,264 +53,55 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = "no disk label"; - int i; - struct disklabel minilabel, fallbacklabel; + 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; - minilabel = fallbacklabel = *lp; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - msg = readbsdlabel(bp, strat, 0, LABELSECTOR, LABELOFFSET, lp, - spoofonly); - if (msg) - *lp = minilabel; - if (msg) { - msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) { - /* Fallback alternative */ - fallbacklabel = *lp; - *lp = minilabel; - } - } - /* Record metainformation about the disklabel. */ - if (msg == NULL) { - osdep->labelsector = bp->b_blkno; + if (spoofonly) + goto doslabel; + + bp->b_blkno = LABELSECTOR; + bp->b_cylinder = 0; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) { + msg = "disk label read error"; + goto done; } + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) + goto done; + +doslabel: + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + #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 - /* If there was an error, still provide a decent fake one. */ - if (msg) - *lp = fallbacklabel; - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); - return (msg); -} - -/* - * If dos partition table requested, attempt to load it and - * find disklabel inside a DOS partition. Return buffer - * for use in signalling errors if requested. - * - * We would like to check if each MBR has a valid BOOT_MAGIC, but - * we cannot because it doesn't always exist. So.. we assume the - * MBR is valid. - */ -char * -readdoslabel(struct buf *bp, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *osdep, - int *partoffp, int *cylp, int spoofonly) -{ - struct dos_partition dp[NDOSPART], *dp2; - struct partition *pp; - unsigned long extoff = 0; - unsigned int fattest; - daddr64_t part_blkno = DOSBBSECTOR; - char *msg = NULL; - int dospartoff, cyl, i, ourpart = -1; - int wander = 1, n = 0, loop = 0; - - if (lp->d_secpercyl == 0) { - msg = "invalid label, d_secpercyl == 0"; - return (msg); - } - if (lp->d_secsize == 0) { - msg = "invalid label, d_secsize == 0"; - return (msg); - } - - /* do dos partitions in the process of getting disklabel? */ - dospartoff = 0; - cyl = I386_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"; - if (partoffp) - *partoffp = -1; - return (msg); - } - 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: - - /* record the OpenBSD partition's placement for the caller */ - if (partoffp) - *partoffp = dospartoff; - if (cylp) - *cylp = cyl; - - /* next, dig out disk label */ - msg = readbsdlabel(bp, strat, cyl, dospartoff + I386_LABELSECTOR, -1, - lp, spoofonly); - return (msg); } @@ -387,54 +112,31 @@ int writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep) { - char *msg = "no disk label"; + u_int64_t csum = 0, *p; + struct disklabel *dlp; struct buf *bp = NULL; - struct disklabel dl; - struct cpu_disklabel cdl; - int labeloffset, error, i, partoff = 0, cyl = 0, needcsum = 0; - u_int64_t csum, *p; + int error, i; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - /* - * I once played with the thought of using osdep->label{tag,sector} - * as a cache for knowing where (and what) to write. However, now I - * think it might be useful to reprobe if someone has written - * a newer disklabel of another type with disklabel(8) and -r. - */ - dl = *lp; - msg = readbsdlabel(bp, strat, 0, LABELSECTOR, LABELOFFSET, &dl, 0); - labeloffset = LABELOFFSET; - if (msg == NULL) - needcsum = 1; - if (msg) { - dl = *lp; - msg = readdoslabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = I386_LABELOFFSET; - } - if (msg) { - if (partoff == -1) { - error = EIO; - goto done; - } - - /* Write it in the regular place with native byte order. */ - labeloffset = LABELOFFSET; - bp->b_blkno = partoff + LABELSECTOR; - bp->b_cylinder = cyl; - bp->b_bcount = lp->d_secsize; - } + bp->b_blkno = LABELSECTOR; + bp->b_cylinder = 0; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if ((error = biowait(bp)) != 0) + goto done; - *(struct disklabel *)(bp->b_data + labeloffset) = *lp; + /* Write it in the regular place. */ + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); + *dlp = *lp; - /* Alpha bootblocks are checksummed. */ - if (needcsum) { - for (csum = i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++) - csum += *p++; - *p = csum; - } + /* Alpha bootblocks require a checksum over the sector */ + for (i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++) + csum += *p++; + *p = csum; bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); diff --git a/sys/arch/alpha/include/disklabel.h b/sys/arch/alpha/include/disklabel.h index 12523a08d15..f5c9c41f82e 100644 --- a/sys/arch/alpha/include/disklabel.h +++ b/sys/arch/alpha/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.20 2007/06/10 05:42:48 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */ +/* $OpenBSD: disklabel.h,v 1.21 2007/06/17 00:27:24 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -34,55 +33,9 @@ #ifndef _MACHINE_DISKLABEL_H_ #define _MACHINE_DISKLABEL_H_ -#define I386_LABELSECTOR 1 /* sector containing label */ -#define I386_LABELOFFSET 0 /* offset of label in sector */ - #define LABELSECTOR 0 #define LABELOFFSET 64 - #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ - -/* DOS partition table -- located in boot block */ -#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ -#define DOSPARTOFF 446 -#define DOSACTIVE 0x80 -#define NDOSPART 4 -#define DOSMBR_SIGNATURE 0xaa55 -#define DOSMBR_SIGNATURE_OFF 0x1fe - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) struct cpu_disklabel { int labelsector; 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_ */ diff --git a/sys/arch/arm/arm/disksubr.c b/sys/arch/arm/arm/disksubr.c index f8b9d9eaa97..fe58a178d2c 100644 --- a/sys/arch/arm/arm/disksubr.c +++ b/sys/arch/arm/arm/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.44 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.45 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> /* @@ -63,227 +59,31 @@ 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; - unsigned long extoff = 0; - unsigned int fattest; struct buf *bp = NULL; - daddr64_t part_blkno = DOSBBSECTOR; - 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; /* 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 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: @@ -291,7 +91,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -303,73 +102,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/arm/include/disklabel.h b/sys/arch/arm/include/disklabel.h index d0ca438166d..621c3ae8de1 100644 --- a/sys/arch/arm/include/disklabel.h +++ b/sys/arch/arm/include/disklabel.h @@ -1,6 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.11 2006/10/20 23:47:42 krw Exp $ */ -/* $OpenBSD: disklabel.h,v 1.11 2006/10/20 23:47:42 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.2 2001/11/25 19:02:03 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.12 2007/06/17 00:27:26 deraadt Exp $ */ /* * Copyright (c) 1994 Mark Brinicombe. @@ -35,14 +33,6 @@ * 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. - * - * RiscBSD kernel project - * - * disklabel.h - * - * machine specific disk label info - * - * Created : 04/10/94 */ #ifndef _ARM_DISKLABEL_H_ @@ -51,58 +41,6 @@ #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: XX?c */ - -#if 0 -#include <arm/disklabel_acorn.h> -#include <sys/disklabel_mbr.h> -#endif - -/* MBR partition table */ -#define DOSBBSECTOR 0 /* MBR sector number */ -#define DOSPARTOFF 446 /* Offset of MBR partition table */ -#define NDOSPART 4 /* # of partitions in MBR */ -#define DOSMAGICOFF 510 /* Offset of magic number */ -#define DOSMAGIC 0xaa55 /* Actual magic number */ -#define MBRMAGIC DOSMAGIC -#define DOSMBR_SIGNATURE MBRMAGIC -#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF -#define DOSACTIVE 0x80 - - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) - struct cpu_disklabel { }; diff --git a/sys/arch/armish/include/disklabel.h b/sys/arch/armish/include/disklabel.h index cef55a0c6c6..1c9c62e6cce 100644 --- a/sys/arch/armish/include/disklabel.h +++ b/sys/arch/armish/include/disklabel.h @@ -1,4 +1,3 @@ -/* $OpenBSD: disklabel.h,v 1.1 2006/05/29 17:13:19 drahn Exp $ */ -/* $NetBSD: disklabel.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.2 2007/06/17 00:27:26 deraadt Exp $ */ #include <arm/disklabel.h> diff --git a/sys/arch/aviion/aviion/disksubr.c b/sys/arch/aviion/aviion/disksubr.c index b3b1593aa14..db0f865e2c9 100644 --- a/sys/arch/aviion/aviion/disksubr.c +++ b/sys/arch/aviion/aviion/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.35 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.36 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> /* @@ -63,227 +59,31 @@ 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; - unsigned long extoff = 0; - unsigned int fattest; struct buf *bp = NULL; - daddr64_t part_blkno = DOSBBSECTOR; - 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; /* 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 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_GETPOFFSET(&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) + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) 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"; - 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: @@ -291,7 +91,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -303,72 +102,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/aviion/include/disklabel.h b/sys/arch/aviion/include/disklabel.h index 6ebfd898405..e97b301aea7 100644 --- a/sys/arch/aviion/include/disklabel.h +++ b/sys/arch/aviion/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.7 2006/10/20 23:47:42 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.2 2001/11/25 19:02:03 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.8 2007/06/17 00:27:26 deraadt Exp $ */ /* * Copyright (c) 1994 Mark Brinicombe. @@ -34,14 +33,6 @@ * 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. - * - * RiscBSD kernel project - * - * disklabel.h - * - * machine specific disk label info - * - * Created : 04/10/94 */ #ifndef _AVIION_DISKLABEL_H_ @@ -50,50 +41,6 @@ #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: XX?c */ - -/* MBR partition table */ -#define DOSBBSECTOR 0 /* MBR sector number */ -#define DOSPARTOFF 446 /* Offset of MBR partition table */ -#define NDOSPART 4 /* # of partitions in MBR */ -#define DOSMAGICOFF 510 /* Offset of magic number */ -#define DOSMAGIC 0xaa55 /* Actual magic number */ -#define MBRMAGIC DOSMAGIC -#define DOSMBR_SIGNATURE MBRMAGIC -#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF -#define DOSACTIVE 0x80 - - -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_OPENBSD 0xa6 /* OpenBSD partition type */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) struct cpu_disklabel { }; diff --git a/sys/arch/cats/include/disklabel.h b/sys/arch/cats/include/disklabel.h index 4f02974008d..e7f8b010c8e 100644 --- a/sys/arch/cats/include/disklabel.h +++ b/sys/arch/cats/include/disklabel.h @@ -1,4 +1,3 @@ -/* $OpenBSD: disklabel.h,v 1.1 2004/02/01 05:12:54 drahn Exp $ */ -/* $NetBSD: disklabel.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.2 2007/06/17 00:27:27 deraadt Exp $ */ #include <arm/disklabel.h> diff --git a/sys/arch/hp300/hp300/disksubr.c b/sys/arch/hp300/hp300/disksubr.c index fbac9ede54e..a83996d1459 100644 --- a/sys/arch/hp300/hp300/disksubr.c +++ b/sys/arch/hp300/hp300/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.39 2007/06/14 03:35:29 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.40 2007/06/17 00:27:28 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.9 1997/04/01 03:12:13 scottr Exp $ */ /* @@ -33,8 +33,6 @@ * 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 8.5 (Berkeley) 1/21/94 */ #include <sys/param.h> @@ -56,74 +54,50 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - struct disklabel *dlp; - int i; - char *msg = NULL; + 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; + + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly) goto done; - bp = geteblk((int)lp->d_secsize); - bp->b_dev = dev; bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = LABELSECTOR / lp->d_secpercyl; (*strat)(bp); - if (biowait(bp)) + if (biowait(bp)) { msg = "disk label I/O error"; - else for (dlp = (struct disklabel *)bp->b_data; - dlp <= (struct disklabel *)((char *)bp->b_data + - DEV_BSIZE - sizeof(*dlp)); - dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - if (msg == NULL) { + goto done; + } + + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) + goto done; + #if defined(CD9660) - if (iso_disklabelspoof(dev, strat, lp) != 0) + if (iso_disklabelspoof(dev, strat, lp) == 0) { + msg = NULL; + goto done; + } #endif - msg = "no disk label"; #if defined(UDF) - if (msg && udf_disklabelspoof(dev, strat, lp) == 0) - msg = NULL; -#endif - } - } 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 (udf_disklabelspoof(dev, strat, lp) == 0) { + msg = NULL; + goto done; } +#endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -136,38 +110,21 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), { struct buf *bp = NULL; struct disklabel *dlp; - int labelpart; int error = 0; - labelpart = DISKPART(dev); - if (DL_GETPOFFSET(&lp->d_partitions[labelpart]) != 0) { - if (DL_GETPOFFSET(&lp->d_partitions[0]) != 0) - return (EXDEV); /* not quite right */ - labelpart = 0; - } + /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); - bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart); + bp->b_dev = dev; bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); - if ((error = biowait(bp))) + if ((error = biowait(bp)) != 0) goto done; - for (dlp = (struct disklabel *)bp->b_data; - dlp <= (struct disklabel *) - ((char *)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/hp300/include/disklabel.h b/sys/arch/hp300/include/disklabel.h index f94fbc6c623..9fb87357f80 100644 --- a/sys/arch/hp300/include/disklabel.h +++ b/sys/arch/hp300/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.5 2001/12/06 23:47:26 miod Exp $ */ -/* $NetBSD: disklabel.h,v 1.1 1994/10/14 18:26:39 cgd Exp $ */ +/* $OpenBSD: disklabel.h,v 1.6 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -34,14 +33,12 @@ #ifndef _MACHINE_DISKLABEL_H_ #define _MACHINE_DISKLABEL_H_ -#define LABELSECTOR (1024 / DEV_BSIZE) /* sector containing label */ +#define LABELSECTOR 2 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ /* Just a dummy */ struct cpu_disklabel { - /* EMPTY */ }; #endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/hppa/hppa/disksubr.c b/sys/arch/hppa/hppa/disksubr.c index 28c79688365..2a53a5d0bdf 100644 --- a/sys/arch/hppa/hppa/disksubr.c +++ b/sys/arch/hppa/hppa/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.65 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.66 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -30,91 +30,18 @@ * 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 - */ - -/* - * This disksubr.c module started to take its present form on OpenBSD/alpha - * but it was always thought it should be made completely MI and not need to - * be in that alpha-specific tree at all. - * - * XXX HPUX disklabel is not understood yet. */ #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> -char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int, - int, struct disklabel *, int); -char *readdoslabel(struct buf *, void (*)(struct buf *), - struct disklabel *, struct cpu_disklabel *, int *, int *, int); char *readliflabel(struct buf *, void (*)(struct buf *), struct disklabel *, struct cpu_disklabel *, int *, int *, int); /* - * Try to read a standard BSD disklabel at a certain sector. - */ -char * -readbsdlabel(struct buf *bp, void (*strat)(struct buf *), - int cyl, int sec, int off, struct disklabel *lp, int spoofonly) -{ - struct disklabel *dlp; - char *msg = NULL; - u_int16_t cksum; - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) - return (NULL); - - bp->b_blkno = sec; - 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"; - return (msg); - } - - /* - * If off is negative, search until the end of the sector for - * the label, otherwise, just look at the specific location - * we're given. - */ - dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0)); - do { - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - if (msg == NULL) - msg = "no disk label"; - } else { - cksum = dkcksum(dlp); - if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) { - msg = "disk label corrupted"; - } else { - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; - msg = NULL; - break; - } - } - if (off >= 0) - break; - dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t)); - } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - - sizeof(*dlp))); - return (msg); -} - -/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: @@ -129,259 +56,41 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = "no disk label"; - int i; - struct disklabel minilabel, fallbacklabel; - - /* 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"; + char *msg; + + 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; - minilabel = fallbacklabel = *lp; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - msg = readliflabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) - *lp = minilabel; - if (msg) { - msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) { - /* Fallback alternative XXX always valid? */ - fallbacklabel = *lp; - *lp = minilabel; - } - } + msg = readliflabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; #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 - /* If there was an error, still provide a decent fake one. */ - if (msg) - *lp = fallbacklabel; - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); - return (msg); -} - -/* - * If dos partition table requested, attempt to load it and - * find disklabel inside a DOS partition. Return buffer - * for use in signalling errors if requested. - * - * We would like to check if each MBR has a valid BOOT_MAGIC, but - * we cannot because it doesn't always exist. So.. we assume the - * MBR is valid. - */ -char * -readdoslabel(struct buf *bp, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *osdep, - int *partoffp, int *cylp, int spoofonly) -{ - struct dos_partition dp[NDOSPART], *dp2; - struct partition *pp; - unsigned long extoff = 0; - unsigned int fattest; - daddr64_t part_blkno = DOSBBSECTOR; - char *msg = NULL; - int dospartoff, cyl, i, ourpart = -1; - int wander = 1, n = 0, loop = 0; - - if (lp->d_secpercyl == 0) { - msg = "invalid label, d_secpercyl == 0"; - return (msg); - } - if (lp->d_secsize == 0) { - msg = "invalid label, d_secsize == 0"; - return (msg); - } - - /* 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"; - if (partoffp) - *partoffp = -1; - return (msg); - } - 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: - - /* record the OpenBSD partition's placement for the caller */ - if (partoffp) - *partoffp = dospartoff; - if (cylp) - *cylp = cyl; - - /* next, dig out disk label */ - msg = readbsdlabel(bp, strat, cyl, dospartoff + LABELSECTOR, -1, - lp, spoofonly); - return (msg); } @@ -390,7 +99,10 @@ readliflabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int *partoffp, int *cylp, int spoofonly) { - int fsoff; + struct buf *dbp = NULL; + struct lifdir *p; + char *msg = NULL; + int fsoff = 0; /* read LIF volume header */ bp->b_blkno = btodb(LIF_VOLSTART); @@ -398,148 +110,147 @@ readliflabel(struct buf *bp, void (*strat)(struct buf *), bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = btodb(LIF_VOLSTART) / lp->d_secpercyl; (*strat)(bp); - - if (biowait(bp)) { - if (partoffp) - *partoffp = -1; + if (biowait(bp)) return "LIF volume header I/O error"; - } - bcopy (bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol)); + bcopy(bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol)); if (osdep->u._hppa.lifvol.vol_id != LIF_VOL_ID) { fsoff = 0; - } else { - struct lifdir *p; - struct buf *dbp; - dev_t dev; + goto finished; + } + + dbp = geteblk(LIF_DIRSIZE); + dbp->b_dev = bp->b_dev; + + /* read LIF directory */ + dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr); + dbp->b_bcount = lp->d_secsize; + dbp->b_flags = B_BUSY | B_READ; + dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; + (*strat)(dbp); + + if (biowait(dbp)) { + msg = "LIF directory I/O error"; + goto done; + } - dev = bp->b_dev; - dbp = geteblk(LIF_DIRSIZE); - dbp->b_dev = dev; + bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE); + + /* scan for LIF_DIR_FS dir entry */ + for (fsoff = -1, p = &osdep->u._hppa.lifdir[0]; + fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) { + if (p->dir_type == LIF_DIR_FS || + p->dir_type == LIF_DIR_HPLBL) + break; + } + + if (p->dir_type == LIF_DIR_FS) { + fsoff = lifstodb(p->dir_addr); + goto finished; + } + + /* Only came here to find the offset... */ + if (partoffp && spoofonly) + goto finished; + + if (p->dir_type == LIF_DIR_HPLBL) { + struct hpux_label *hl; + struct partition *pp; + u_int8_t fstype; + int i; /* read LIF directory */ - dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr); + dbp->b_blkno = lifstodb(p->dir_addr); dbp->b_bcount = lp->d_secsize; dbp->b_flags = B_BUSY | B_READ; dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; (*strat)(dbp); if (biowait(dbp)) { - if (partoffp) - *partoffp = -1; - - dbp->b_flags |= B_INVAL; - brelse(dbp); - return ("LIF directory I/O error"); + msg = "HPUX label I/O error"; + goto done; } - bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE); - dbp->b_flags |= B_INVAL; - brelse(dbp); + bcopy(dbp->b_data, &osdep->u._hppa.hplabel, + sizeof(osdep->u._hppa.hplabel)); - /* scan for LIF_DIR_FS dir entry */ - for (fsoff = -1, p = &osdep->u._hppa.lifdir[0]; - fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) { - if (p->dir_type == LIF_DIR_FS || - p->dir_type == LIF_DIR_HPLBL) - break; + hl = &osdep->u._hppa.hplabel; + if (hl->hl_magic1 != hl->hl_magic2 || + hl->hl_magic != HPUX_MAGIC || hl->hl_version != 1) { + msg = "HPUX label magic mismatch"; + goto done; } - if (p->dir_type == LIF_DIR_FS) - fsoff = lifstodb(p->dir_addr); - else if (p->dir_type == LIF_DIR_HPLBL) { - struct hpux_label *hl; - struct partition *pp; - u_int8_t fstype; - int i; - - dev = bp->b_dev; - dbp = geteblk(LIF_DIRSIZE); - dbp->b_dev = dev; - - /* read LIF directory */ - dbp->b_blkno = lifstodb(p->dir_addr); - dbp->b_bcount = lp->d_secsize; - dbp->b_flags = B_BUSY | B_READ; - dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; - (*strat)(dbp); - - if (biowait(dbp)) { - if (partoffp) - *partoffp = -1; - - dbp->b_flags |= B_INVAL; - brelse(dbp); - return ("HOUX label I/O error"); - } - - bcopy(dbp->b_data, &osdep->u._hppa.hplabel, - sizeof(osdep->u._hppa.hplabel)); - dbp->b_flags |= B_INVAL; - brelse(dbp); - - hl = &osdep->u._hppa.hplabel; - if (hl->hl_magic1 != hl->hl_magic2 || - hl->hl_magic != HPUX_MAGIC || - hl->hl_version != 1) { - if (partoffp) - *partoffp = -1; - - return "HPUX label magic mismatch"; - } - - lp->d_bbsize = 8192; - lp->d_sbsize = 8192; - for (i = 0; i < MAXPARTITIONS; i++) { - DL_SETPSIZE(&lp->d_partitions[i], 0); - DL_SETPOFFSET(&lp->d_partitions[i], 0); - lp->d_partitions[i].p_fstype = 0; - } - - for (i = 0; i < HPUX_MAXPART; i++) { - if (!hl->hl_flags[i]) - continue; - - if (hl->hl_flags[i] == HPUX_PART_ROOT) { - pp = &lp->d_partitions[0]; - fstype = FS_BSDFFS; - } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { - pp = &lp->d_partitions[1]; - fstype = FS_SWAP; - } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { - pp = &lp->d_partitions[RAW_PART + 1]; - fstype = FS_BSDFFS; - } else - continue; - - DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2); - DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2); - pp->p_fstype = fstype; - } - - DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); - DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); - lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; - lp->d_npartitions = MAXPARTITIONS; - lp->d_magic = DISKMAGIC; - lp->d_magic2 = DISKMAGIC; - lp->d_checksum = 0; - lp->d_checksum = dkcksum(lp); - - return (NULL); + lp->d_bbsize = 8192; + lp->d_sbsize = 8192; + for (i = 0; i < MAXPARTITIONS; i++) { + DL_SETPSIZE(&lp->d_partitions[i], 0); + DL_SETPOFFSET(&lp->d_partitions[i], 0); + lp->d_partitions[i].p_fstype = 0; } - /* if no suitable lifdir entry found assume zero */ - if (fsoff < 0) { - fsoff = 0; + for (i = 0; i < HPUX_MAXPART; i++) { + if (!hl->hl_flags[i]) + continue; + if (hl->hl_flags[i] == HPUX_PART_ROOT) { + pp = &lp->d_partitions[0]; + fstype = FS_BSDFFS; + } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { + pp = &lp->d_partitions[1]; + fstype = FS_SWAP; + } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { + pp = &lp->d_partitions[RAW_PART + 1]; + fstype = FS_BSDFFS; + } else + continue; + + DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2); + DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2); + pp->p_fstype = fstype; } + + DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); + DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_npartitions = MAXPARTITIONS; + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_version = 1; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + /* drop through */ } +finished: + /* if no suitable lifdir entry found assume zero */ + if (fsoff < 0) + fsoff = 0; if (partoffp) *partoffp = fsoff; - return readbsdlabel(bp, strat, 0, fsoff + LABELSECTOR, - LABELOFFSET, lp, spoofonly); + if (spoofonly) + goto done; + + bp->b_blkno = fsoff + LABELSECTOR; + bp->b_cylinder = 0; + 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)) { + msg = "disk label I/O error"; + goto done; + } + + return checkdisklabel(bp->b_data + LABELOFFSET, lp); + +done: + if (dbp) { + dbp->b_flags |= B_INVAL; + brelse(dbp); + } + return (msg); } /* @@ -549,42 +260,43 @@ int writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep) { - char *msg = "no disk label"; - struct buf *bp; - struct disklabel dl; - struct cpu_disklabel cdl; - int labeloffset, error, partoff = 0, cyl = 0; + int error, partoff = -1, cyl = 0; + struct disklabel *dlp; + struct buf *bp = NULL; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - dl = *lp; - msg = readliflabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - if (msg) { - dl = *lp; - msg = readdoslabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - } - if (msg) { - if (partoff == -1) - return EIO; - - /* Write it in the regular place with native byte order. */ - labeloffset = LABELOFFSET; - bp->b_blkno = partoff + LABELSECTOR; - bp->b_cylinder = cyl; - bp->b_bcount = lp->d_secsize; - } + if (readliflabel(bp, strat, lp, osdep, &partoff, &cyl, 1) == NULL) + goto writeit; - *(struct disklabel *)(bp->b_data + labeloffset) = *lp; + if (readdoslabel(bp, strat, lp, osdep, &partoff, &cyl, 1) == NULL) + goto writeit; + + error = EIO; + goto done; + +writeit: + /* 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 ((error = biowait(bp)) != 0) + goto done; + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); + *dlp = *lp; bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); error = biowait(bp); - bp->b_flags |= B_INVAL; - brelse(bp); +done: + if (bp) { + bp->b_flags |= B_INVAL; + brelse(bp); + } return (error); } diff --git a/sys/arch/hppa/include/disklabel.h b/sys/arch/hppa/include/disklabel.h index a810e85eab3..c8fb499c60b 100644 --- a/sys/arch/hppa/include/disklabel.h +++ b/sys/arch/hppa/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.17 2007/06/07 02:55:12 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */ +/* $OpenBSD: disklabel.h,v 1.18 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -36,50 +35,7 @@ #define LABELSECTOR 1 #define LABELOFFSET 0 - #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ - -/* DOS partition table -- located in boot block */ -#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ -#define DOSPARTOFF 446 -#define DOSACTIVE 0x80 -#define NDOSPART 4 -#define DOSMBR_SIGNATURE 0xaa55 -#define DOSMBR_SIGNATURE_OFF 0x1fe - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) /* * volume header for "LIF" format volumes diff --git a/sys/arch/hppa64/hppa64/disksubr.c b/sys/arch/hppa64/hppa64/disksubr.c index 7e9125b7921..fb62b2850e0 100644 --- a/sys/arch/hppa64/hppa64/disksubr.c +++ b/sys/arch/hppa64/hppa64/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.48 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.49 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -30,91 +30,18 @@ * 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 - */ - -/* - * This disksubr.c module started to take its present form on OpenBSD/alpha - * but it was always thought it should be made completely MI and not need to - * be in that alpha-specific tree at all. - * - * XXX HPUX disklabel is not understood yet. */ #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> -char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int, - int, struct disklabel *, int); -char *readdoslabel(struct buf *, void (*)(struct buf *), - struct disklabel *, struct cpu_disklabel *, int *, int *, int); char *readliflabel(struct buf *, void (*)(struct buf *), struct disklabel *, struct cpu_disklabel *, int *, int *, int); /* - * Try to read a standard BSD disklabel at a certain sector. - */ -char * -readbsdlabel(struct buf *bp, void (*strat)(struct buf *), - int cyl, int sec, int off, struct disklabel *lp, int spoofonly) -{ - struct disklabel *dlp; - char *msg = NULL; - u_int16_t cksum; - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) - return (NULL); - - bp->b_blkno = sec; - 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"; - return (msg); - } - - /* - * If off is negative, search until the end of the sector for - * the label, otherwise, just look at the specific location - * we're given. - */ - dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0)); - do { - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - if (msg == NULL) - msg = "no disk label"; - } else { - cksum = dkcksum(dlp); - if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) { - msg = "disk label corrupted"; - } else { - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; - msg = NULL; - break; - } - } - if (off >= 0) - break; - dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t)); - } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - - sizeof(*dlp))); - return (msg); -} - -/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: @@ -129,259 +56,41 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = "no disk label"; - int i; - struct disklabel minilabel, fallbacklabel; - - /* 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"; + char *msg; + + 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; - minilabel = fallbacklabel = *lp; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - msg = readliflabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) - *lp = minilabel; - if (msg) { - msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) { - /* Fallback alternative XXX always valid? */ - fallbacklabel = *lp; - *lp = minilabel; - } - } + msg = readliflabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; #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 - /* If there was an error, still provide a decent fake one. */ - if (msg) - *lp = fallbacklabel; - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); - return (msg); -} - -/* - * If dos partition table requested, attempt to load it and - * find disklabel inside a DOS partition. Return buffer - * for use in signalling errors if requested. - * - * We would like to check if each MBR has a valid BOOT_MAGIC, but - * we cannot because it doesn't always exist. So.. we assume the - * MBR is valid. - */ -char * -readdoslabel(struct buf *bp, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *osdep, - int *partoffp, int *cylp, int spoofonly) -{ - struct dos_partition dp[NDOSPART], *dp2; - struct partition *pp; - unsigned long extoff = 0; - unsigned int fattest; - daddr64_t part_blkno = DOSBBSECTOR; - char *msg = NULL; - int dospartoff, cyl, i, ourpart = -1; - int wander = 1, n = 0, loop = 0; - - if (lp->d_secpercyl == 0) { - msg = "invalid label, d_secpercyl == 0"; - return (msg); - } - if (lp->d_secsize == 0) { - msg = "invalid label, d_secsize == 0"; - return (msg); - } - - /* 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"; - if (partoffp) - *partoffp = -1; - return (msg); - } - 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: - - /* record the OpenBSD partition's placement for the caller */ - if (partoffp) - *partoffp = dospartoff; - if (cylp) - *cylp = cyl; - - /* next, dig out disk label */ - msg = readbsdlabel(bp, strat, cyl, dospartoff + LABELSECTOR, -1, - lp, spoofonly); - return (msg); } @@ -390,7 +99,10 @@ readliflabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int *partoffp, int *cylp, int spoofonly) { - int fsoff; + struct buf *dbp = NULL; + struct lifdir *p; + char *msg = NULL; + int fsoff = 0; /* read LIF volume header */ bp->b_blkno = btodb(LIF_VOLSTART); @@ -398,148 +110,147 @@ readliflabel(struct buf *bp, void (*strat)(struct buf *), bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = btodb(LIF_VOLSTART) / lp->d_secpercyl; (*strat)(bp); - - if (biowait(bp)) { - if (partoffp) - *partoffp = -1; + if (biowait(bp)) return "LIF volume header I/O error"; - } - bcopy (bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol)); + bcopy(bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol)); if (osdep->u._hppa.lifvol.vol_id != LIF_VOL_ID) { fsoff = 0; - } else { - struct lifdir *p; - struct buf *dbp; - dev_t dev; + goto finished; + } + + dbp = geteblk(LIF_DIRSIZE); + dbp->b_dev = bp->b_dev; + + /* read LIF directory */ + dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr); + dbp->b_bcount = lp->d_secsize; + dbp->b_flags = B_BUSY | B_READ; + dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; + (*strat)(dbp); + + if (biowait(dbp)) { + msg = "LIF directory I/O error"; + goto done; + } - dev = bp->b_dev; - dbp = geteblk(LIF_DIRSIZE); - dbp->b_dev = dev; + bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE); + + /* scan for LIF_DIR_FS dir entry */ + for (fsoff = -1, p = &osdep->u._hppa.lifdir[0]; + fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) { + if (p->dir_type == LIF_DIR_FS || + p->dir_type == LIF_DIR_HPLBL) + break; + } + + if (p->dir_type == LIF_DIR_FS) { + fsoff = lifstodb(p->dir_addr); + goto finished; + } + + /* Only came here to find the offset... */ + if (partoffp && spoofonly) + goto finished; + + if (p->dir_type == LIF_DIR_HPLBL) { + struct hpux_label *hl; + struct partition *pp; + u_int8_t fstype; + int i; /* read LIF directory */ - dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr); + dbp->b_blkno = lifstodb(p->dir_addr); dbp->b_bcount = lp->d_secsize; dbp->b_flags = B_BUSY | B_READ; dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; (*strat)(dbp); if (biowait(dbp)) { - if (partoffp) - *partoffp = -1; - - dbp->b_flags |= B_INVAL; - brelse(dbp); - return ("LIF directory I/O error"); + msg = "HPUX label I/O error"; + goto done; } - bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE); - dbp->b_flags |= B_INVAL; - brelse(dbp); + bcopy(dbp->b_data, &osdep->u._hppa.hplabel, + sizeof(osdep->u._hppa.hplabel)); - /* scan for LIF_DIR_FS dir entry */ - for (fsoff = -1, p = &osdep->u._hppa.lifdir[0]; - fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) { - if (p->dir_type == LIF_DIR_FS || - p->dir_type == LIF_DIR_HPLBL) - break; + hl = &osdep->u._hppa.hplabel; + if (hl->hl_magic1 != hl->hl_magic2 || + hl->hl_magic != HPUX_MAGIC || hl->hl_version != 1) { + msg = "HPUX label magic mismatch"; + goto done; } - if (p->dir_type == LIF_DIR_FS) - fsoff = lifstodb(p->dir_addr); - else if (p->dir_type == LIF_DIR_HPLBL) { - struct hpux_label *hl; - struct partition *pp; - u_int8_t fstype; - int i; - - dev = bp->b_dev; - dbp = geteblk(LIF_DIRSIZE); - dbp->b_dev = dev; - - /* read LIF directory */ - dbp->b_blkno = lifstodb(p->dir_addr); - dbp->b_bcount = lp->d_secsize; - dbp->b_flags = B_BUSY | B_READ; - dbp->b_cylinder = dbp->b_blkno / lp->d_secpercyl; - (*strat)(dbp); - - if (biowait(dbp)) { - if (partoffp) - *partoffp = -1; - - dbp->b_flags |= B_INVAL; - brelse(dbp); - return ("HOUX label I/O error"); - } - - bcopy(dbp->b_data, &osdep->u._hppa.hplabel, - sizeof(osdep->u._hppa.hplabel)); - dbp->b_flags |= B_INVAL; - brelse(dbp); - - hl = &osdep->u._hppa.hplabel; - if (hl->hl_magic1 != hl->hl_magic2 || - hl->hl_magic != HPUX_MAGIC || - hl->hl_version != 1) { - if (partoffp) - *partoffp = -1; - - return "HPUX label magic mismatch"; - } - - lp->d_bbsize = 8192; - lp->d_sbsize = 8192; - for (i = 0; i < MAXPARTITIONS; i++) { - DL_SETPSIZE(&lp->d_partitions[i], 0); - DL_SETPOFFSET(&lp->d_partitions[i], 0); - lp->d_partitions[i].p_fstype = 0; - } - - for (i = 0; i < HPUX_MAXPART; i++) { - if (!hl->hl_flags[i]) - continue; - - if (hl->hl_flags[i] == HPUX_PART_ROOT) { - pp = &lp->d_partitions[0]; - fstype = FS_BSDFFS; - } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { - pp = &lp->d_partitions[1]; - fstype = FS_SWAP; - } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { - pp = &lp->d_partitions[RAW_PART + 1]; - fstype = FS_BSDFFS; - } else - continue; - - DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2); - DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2); - pp->p_fstype = fstype; - } - - DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); - DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); - lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; - lp->d_npartitions = MAXPARTITIONS; - lp->d_magic = DISKMAGIC; - lp->d_magic2 = DISKMAGIC; - lp->d_checksum = 0; - lp->d_checksum = dkcksum(lp); - - return (NULL); + lp->d_bbsize = 8192; + lp->d_sbsize = 8192; + for (i = 0; i < MAXPARTITIONS; i++) { + DL_SETPSIZE(&lp->d_partitions[i], 0); + DL_SETPOFFSET(&lp->d_partitions[i], 0); + lp->d_partitions[i].p_fstype = 0; } - /* if no suitable lifdir entry found assume zero */ - if (fsoff < 0) { - fsoff = 0; + for (i = 0; i < HPUX_MAXPART; i++) { + if (!hl->hl_flags[i]) + continue; + if (hl->hl_flags[i] == HPUX_PART_ROOT) { + pp = &lp->d_partitions[0]; + fstype = FS_BSDFFS; + } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { + pp = &lp->d_partitions[1]; + fstype = FS_SWAP; + } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { + pp = &lp->d_partitions[RAW_PART + 1]; + fstype = FS_BSDFFS; + } else + continue; + + DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2); + DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2); + pp->p_fstype = fstype; } + + DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); + DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_npartitions = MAXPARTITIONS; + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_version = 1; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + /* drop through */ } +finished: + /* if no suitable lifdir entry found assume zero */ + if (fsoff < 0) + fsoff = 0; if (partoffp) *partoffp = fsoff; - return readbsdlabel(bp, strat, 0, fsoff + LABELSECTOR, - LABELOFFSET, lp, spoofonly); + if (spoofonly) + goto done; + + bp->b_blkno = fsoff + LABELSECTOR; + bp->b_cylinder = 0; + 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)) { + msg = "disk label I/O error"; + goto done; + } + + return checkdisklabel(bp->b_data + LABELOFFSET, lp); + +done: + if (dbp) { + dbp->b_flags |= B_INVAL; + brelse(dbp); + } + return (msg); } /* @@ -549,42 +260,43 @@ int writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep) { - char *msg = "no disk label"; - struct buf *bp; - struct disklabel dl; - struct cpu_disklabel cdl; - int labeloffset, error, partoff = 0, cyl = 0; + int error, partoff = -1, cyl = 0; + struct disklabel *dlp; + struct buf *bp = NULL; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - dl = *lp; - msg = readliflabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - if (msg) { - dl = *lp; - msg = readdoslabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - } - if (msg) { - if (partoff == -1) - return EIO; - - /* Write it in the regular place with native byte order. */ - labeloffset = LABELOFFSET; - bp->b_blkno = partoff + LABELSECTOR; - bp->b_cylinder = cyl; - bp->b_bcount = lp->d_secsize; - } + if (readliflabel(bp, strat, lp, osdep, &partoff, &cyl, 1) == NULL) + goto writeit; - *(struct disklabel *)(bp->b_data + labeloffset) = *lp; + if (readdoslabel(bp, strat, lp, osdep, &partoff, &cyl, 1) == NULL) + goto writeit; + + error = EIO; + goto done; + +writeit: + /* 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 ((error = biowait(bp)) != 0) + goto done; + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); + *dlp = *lp; bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); error = biowait(bp); - bp->b_flags |= B_INVAL; - brelse(bp); +done: + if (bp) { + bp->b_flags |= B_INVAL; + brelse(bp); + } return (error); } diff --git a/sys/arch/hppa64/include/disklabel.h b/sys/arch/hppa64/include/disklabel.h index 83ea80baf88..596696c2e64 100644 --- a/sys/arch/hppa64/include/disklabel.h +++ b/sys/arch/hppa64/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.11 2007/06/07 02:55:12 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */ +/* $OpenBSD: disklabel.h,v 1.12 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -36,50 +35,7 @@ #define LABELSECTOR 1 #define LABELOFFSET 0 - #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ - -/* DOS partition table -- located in boot block */ -#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ -#define DOSPARTOFF 446 -#define DOSACTIVE 0x80 -#define NDOSPART 4 -#define DOSMBR_SIGNATURE 0xaa55 -#define DOSMBR_SIGNATURE_OFF 0x1fe - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) /* * volume header for "LIF" format volumes diff --git a/sys/arch/i386/i386/disksubr.c b/sys/arch/i386/i386/disksubr.c index f44221b04fb..9e6bbb939be 100644 --- a/sys/arch/i386/i386/disksubr.c +++ b/sys/arch/i386/i386/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.90 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.91 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/i386/include/disklabel.h b/sys/arch/i386/include/disklabel.h index 5a960c6dfb7..009a100a3a0 100644 --- a/sys/arch/i386/include/disklabel.h +++ b/sys/arch/i386/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.32 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.33 2007/06/17 00:27:27 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_ */ diff --git a/sys/arch/landisk/include/disklabel.h b/sys/arch/landisk/include/disklabel.h index 4d7cc146698..9da9360f5a0 100644 --- a/sys/arch/landisk/include/disklabel.h +++ b/sys/arch/landisk/include/disklabel.h @@ -1 +1,3 @@ +/* $OpenBSD: disklabel.h,v 1.2 2007/06/17 00:27:27 deraadt Exp $ */ + #include <sh/disklabel.h> diff --git a/sys/arch/landisk/landisk/disksubr.c b/sys/arch/landisk/landisk/disksubr.c index fc73f3d3ab8..2f55984164f 100644 --- a/sys/arch/landisk/landisk/disksubr.c +++ b/sys/arch/landisk/landisk/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.32 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.33 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> /* @@ -63,227 +59,31 @@ 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; - unsigned long extoff = 0; - unsigned int fattest; struct buf *bp = NULL; - daddr64_t part_blkno = DOSBBSECTOR; - 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; /* 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 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: @@ -291,7 +91,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -303,73 +102,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/luna88k/include/disklabel.h b/sys/arch/luna88k/include/disklabel.h index f2eae514c98..73ddbdee561 100644 --- a/sys/arch/luna88k/include/disklabel.h +++ b/sys/arch/luna88k/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.2 2006/10/04 03:23:01 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.2 2000/01/28 02:25:24 nisimura Exp $ */ +/* $OpenBSD: disklabel.h,v 1.3 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -37,7 +36,6 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 64 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ /* * This holds a copy of the whole label block, saved in here by diff --git a/sys/arch/luna88k/luna88k/disksubr.c b/sys/arch/luna88k/luna88k/disksubr.c index e625bac11ab..b09a74d8916 100644 --- a/sys/arch/luna88k/luna88k/disksubr.c +++ b/sys/arch/luna88k/luna88k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.29 2007/06/14 03:41:21 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.30 2007/06/17 00:27:28 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.12 2002/02/19 17:09:44 wiz Exp $ */ /* @@ -34,14 +34,6 @@ * 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. - * - * Credits: - * This file was based mostly on the i386/disksubr.c file: - * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 - * The functions: disklabel_sun_to_bsd, disklabel_bsd_to_sun - * were originally taken from arch/sparc/scsi/sun_disklabel.c - * (which was written by Theo de Raadt) and then substantially - * rewritten by Gordon W. Ross. */ #include <sys/param.h> @@ -118,37 +110,19 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct buf *bp = NULL; struct disklabel *dlp; struct sun_disklabel *slp; - char *msg = NULL; int error, i; + 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"; - 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; - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; /* obtain buffer to probe drive with */ bp = geteblk((int)lp->d_secsize); - - /* next, dig out disk label */ bp->b_dev = dev; + + if (spoofonly) + goto done; + bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; @@ -166,6 +140,16 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; } + slp = (struct sun_disklabel *)clp->cd_block; + if (slp->sl_magic == SUN_DKMAGIC) { + msg = disklabel_om_to_bsd(clp->cd_block, lp); + goto done; + } + + msg = checkdisklabel(clp->cd_block + LABELOFFSET, lp); + if (msg == NULL) + goto done; + #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) { msg = NULL; @@ -178,27 +162,7 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; } #endif - - /* Check for a BSD disk label first. */ - dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); - if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) { - if (dkcksum(dlp) == 0) { - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; /* struct assignment */ - msg = NULL; - goto done; - } - printf("BSD disk label corrupted"); - } - - /* Check for a UniOS/ISI disk label. */ - slp = (struct sun_disklabel *)clp->cd_block; - if (slp->sl_magic == SUN_DKMAGIC) { - msg = disklabel_om_to_bsd(clp->cd_block, lp); - goto done; - } - - memset(clp->cd_block, 0, sizeof(clp->cd_block)); + bzero(clp->cd_block, sizeof(clp->cd_block)); msg = "no disk label"; done: @@ -206,7 +170,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } diff --git a/sys/arch/mac68k/include/disklabel.h b/sys/arch/mac68k/include/disklabel.h index 28820db1a61..1f07b724393 100644 --- a/sys/arch/mac68k/include/disklabel.h +++ b/sys/arch/mac68k/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.6 2002/04/18 22:12:38 miod Exp $ */ -/* $NetBSD: disklabel.h,v 1.2 1996/05/05 06:17:38 briggs Exp $ */ +/* $OpenBSD: disklabel.h,v 1.7 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -35,20 +34,10 @@ #define _MAC68K_DISKLABEL_H_ #define LABELSECTOR 0 /* sector containing label */ -#define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ - -/* - * There is no physical disklabel on disk, since it is constructed from - * the MacOS partition table. - * However, to prevent disklabel -r to kill the disk, define a dummy - * offset outside of vital structures. - */ #define LABELOFFSET 64 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ -/* Just a dummy */ struct cpu_disklabel { - /* EMPTY */ }; #endif /* _MAC68K_DISKLABEL_H_ */ diff --git a/sys/arch/mac68k/mac68k/disksubr.c b/sys/arch/mac68k/mac68k/disksubr.c index 1a23e9bcb32..dfc4dfe9e59 100644 --- a/sys/arch/mac68k/mac68k/disksubr.c +++ b/sys/arch/mac68k/mac68k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.47 2007/06/14 03:35:29 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.48 2007/06/17 00:27:28 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.22 1997/11/26 04:18:20 briggs Exp $ */ /* @@ -28,9 +28,8 @@ * 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 */ + /*- * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, * Michael L. Finch, Bradley A. Grantham, and @@ -87,11 +86,11 @@ #define NUM_PARTS_PROBED 32 -#define ROOT_PART 1 -#define UFS_PART 2 -#define SWAP_PART 3 -#define HFS_PART 4 -#define SCRATCH_PART 5 +#define ROOT_PART 1 +#define UFS_PART 2 +#define SWAP_PART 3 +#define HFS_PART 4 +#define SCRATCH_PART 5 int getFreeLabelEntry(struct disklabel *); int whichType(struct partmapentry *); @@ -110,11 +109,10 @@ getFreeLabelEntry(struct disklabel *lp) int i; for (i = 0; i < MAXPARTITIONS; i++) { - if ((i != RAW_PART) - && (lp->d_partitions[i].p_fstype == FS_UNUSED)) + if (i != RAW_PART && + lp->d_partitions[i].p_fstype == FS_UNUSED) return i; } - return -1; } @@ -129,15 +127,11 @@ whichType(struct partmapentry *part) if (part->pmPartType[0] == '\0') return 0; - if (strcmp(PART_DRIVER_TYPE, (char *)part->pmPartType) == 0) - return 0; - if (strcmp(PART_DRIVER43_TYPE, (char *)part->pmPartType) == 0) - return 0; - if (strcmp(PART_DRIVERATA_TYPE, (char *)part->pmPartType) == 0) - return 0; - if (strcmp(PART_FWB_COMPONENT_TYPE, (char *)part->pmPartType) == 0) - return 0; - if (strcmp(PART_PARTMAP_TYPE, (char *)part->pmPartType) == 0) + if (strcmp(PART_DRIVER_TYPE, (char *)part->pmPartType) == 0 || + strcmp(PART_DRIVER43_TYPE, (char *)part->pmPartType) == 0 || + strcmp(PART_DRIVERATA_TYPE, (char *)part->pmPartType) == 0 || + strcmp(PART_FWB_COMPONENT_TYPE, (char *)part->pmPartType) == 0 || + strcmp(PART_PARTMAP_TYPE, (char *)part->pmPartType) == 0 || return 0; if (strcmp(PART_UNIX_TYPE, (char *)part->pmPartType) == 0) { /* unix part, swap, root, usr */ @@ -148,10 +142,10 @@ whichType(struct partmapentry *part) if (bzb->bzbFlags & BZB_ROOTFS) return ROOT_PART; - if ((bzb->bzbFlags & BZB_USRFS) - || (bzb->bzbFlags & BZB_EXFS4) - || (bzb->bzbFlags & BZB_EXFS5) - || (bzb->bzbFlags & BZB_EXFS6)) + if ((bzb->bzbFlags & BZB_USRFS) || + (bzb->bzbFlags & BZB_EXFS4) || + (bzb->bzbFlags & BZB_EXFS5) || + (bzb->bzbFlags & BZB_EXFS6)) return UFS_PART; if (bzb->bzbType == BZB_TYPESWAP) @@ -176,13 +170,12 @@ whichType(struct partmapentry *part) int fixPartTable(struct partmapentry *partTable, long size, char *base) { - int i; struct partmapentry *pmap; char *s; + int i; for (i = 0; i < NUM_PARTS_PROBED; i++) { pmap = (struct partmapentry *)((i * size) + base + DEV_BSIZE); - partTable[i] = *pmap; pmap = &partTable[i]; @@ -198,7 +191,6 @@ fixPartTable(struct partmapentry *partTable, long size, char *base) if ((*s >= 'a') && (*s <= 'z')) *s = (*s - 'a' + 'A'); } - return NUM_PARTS_PROBED; } @@ -246,12 +238,10 @@ getNamedType(struct partmapentry *part, int num_parts, struct disklabel *lp, printf("disksubr.c: can't do type %d\n", type); break; } - return 0; } skip: } - return -1; } @@ -289,8 +279,7 @@ read_mac_label(char *dlbuf, struct disklabel *lp, struct cpu_disklabel *osdep) if (getNamedType(pmap, num_parts, lp, UFS_PART, 0, &maxslot)) getNamedType(pmap, num_parts, lp, UFS_PART, -1, &maxslot); for (i = 0; i < num_parts; i++) { - int partType; - int slot; + int partType, slot; slot = getFreeLabelEntry(lp); if (slot < 0) @@ -299,12 +288,7 @@ read_mac_label(char *dlbuf, struct disklabel *lp, struct cpu_disklabel *osdep) partType = whichType(&(pmap[i])); switch (partType) { - case ROOT_PART: - /* - * another root part will turn into a plain old - * UFS_PART partition, live with it. - */ case UFS_PART: setPart(&(pmap[i]), lp, FS_BSDFFS, slot); if (slot > maxslot) @@ -330,7 +314,9 @@ read_mac_label(char *dlbuf, struct disklabel *lp, struct cpu_disklabel *osdep) } } lp->d_npartitions = maxslot + 1; - + lp->d_version = 1; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); FREE(pmap, M_DEVBUF); return NULL; } @@ -341,83 +327,70 @@ read_mac_label(char *dlbuf, struct disklabel *lp, struct cpu_disklabel *osdep) * anything required in the strategy routine (e.g., sector size) must be * filled in before calling us. Returns null on success and an error * string on failure. - * - * This will read sector zero. If this contains what looks like a valid - * Macintosh boot sector, we attempt to fill in the disklabel structure. - * If the first longword of the disk is a OpenBSD disk label magic number, - * then we assume that it's a real disklabel and return it. */ char * readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = NULL; - struct disklabel *dlp; - int i, size; - - /* 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"; - 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; + u_int16_t *sbSigp; + int size; + char *msg; - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; size = roundup((NUM_PARTS_PROBED + 1) << DEV_BSHIFT, lp->d_secsize); bp = geteblk(size); bp->b_dev = dev; + bp->b_blkno = LABELSECTOR; bp->b_bcount = size; bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = LABELSECTOR / lp->d_secpercyl; (*strat)(bp); - if (biowait(bp)) + if (biowait(bp)) { msg = "disk label I/O error"; - else { - u_int16_t *sbSigp; - - sbSigp = (u_int16_t *)bp->b_data; - if (*sbSigp == 0x4552) { - msg = read_mac_label(bp->b_data, lp, osdep); - } else { - dlp = (struct disklabel *)(bp->b_data + - LABELOFFSET); - if (dlp->d_magic != DISKMAGIC || - dlp->d_magic2 != DISKMAGIC) { - msg = "no OpenBSD or MacOS disk label"; - } else if (dlp->d_npartitions > MAXPARTITIONS || - dkcksum(dlp) != 0) { - msg = "disk label corrupted"; - } else { - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; - } - } + goto done; } + sbSigp = (u_int16_t *)bp->b_data; + if (*sbSigp == 0x4552) { + msg = read_mac_label(bp->b_data, lp, osdep); + if (msg == NULL) + goto done; + } + + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + + /* Get a MI label */ + bp->b_blkno = LABELSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylinder = LABELSECTOR / lp->d_secpercyl; + (*strat)(bp); + if (biowait(bp)) { + msg = "disk label I/O error"; + goto done; + } + + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) + goto done; + #if defined(CD9660) - if (msg != NULL && 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: @@ -425,7 +398,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -441,18 +413,13 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), { struct buf *bp = NULL; struct disklabel *dlp; - int labelpart; int error = 0; u_int16_t *sbSigp; - labelpart = DISKPART(dev); - if (DL_GETPOFFSET(&lp->d_partitions[labelpart]) != 0) { - if (DL_GETPOFFSET(&lp->d_partitions[0]) != 0) - return (EXDEV); /* not quite right */ - labelpart = 0; - } + /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); - bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), labelpart); + bp->b_dev = dev; + bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; @@ -461,21 +428,15 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), if ((error = biowait(bp)) != 0) goto done; - /* - * Check for MacOS fingerprints - */ + /* Check for MacOS fingerprints */ sbSigp = (u_int16_t *)bp->b_data; if (*sbSigp == 0x4552) { - /* - * Read the partition map again, in case it has changed. - */ - if (readdisklabel(dev, strat, lp, osdep, 0) != NULL) - error = EINVAL; + /* XXX AND THEN DO NOT WRITE?? */ goto done; } dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); - bcopy(lp, dlp, sizeof(struct disklabel)); + *dlp = *lp; bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); error = biowait(bp); diff --git a/sys/arch/macppc/include/disklabel.h b/sys/arch/macppc/include/disklabel.h index 8f0dc9fd57b..d9d76603828 100644 --- a/sys/arch/macppc/include/disklabel.h +++ b/sys/arch/macppc/include/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.11 2006/10/20 23:47:43 krw Exp $ */ +/* $OpenBSD: disklabel.h,v 1.12 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -36,51 +36,6 @@ #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 */ - -/* MBR partition table */ -#define DOSBBSECTOR 0 /* MBR sector number */ -#define DOSPARTOFF 446 /* Offset of MBR partition table */ -#define NDOSPART 4 /* # of partitions in MBR */ -#define DOSMAGICOFF 510 /* Offset of magic number */ -#define DOSMAGIC 0xaa55 /* Actual magic number */ -#define MBRMAGIC DOSMAGIC -#define DOSMBR_SIGNATURE MBRMAGIC -#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF -#define DOSACTIVE 0x80 - -struct dos_partition { - u_int8_t dp_flag; /* default boot flag */ - u_int8_t dp_shd; /* start head, IsN't Always Meaningful */ - u_int8_t dp_ssect; /* start sector, INAM */ - u_int8_t dp_scyl; /* start cylinder, INAM */ - u_int8_t dp_typ; /* partition type */ - u_int8_t dp_ehd; /* end head, INAM */ - u_int8_t dp_esect; /* end sector, INAM */ - u_int8_t dp_ecyl; /* end cylinder, INAM */ - u_int32_t dp_start; /* absolute start 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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) /* HFS/DPME */ diff --git a/sys/arch/macppc/macppc/disksubr.c b/sys/arch/macppc/macppc/disksubr.c index 8f22a779a70..50375684ad4 100644 --- a/sys/arch/macppc/macppc/disksubr.c +++ b/sys/arch/macppc/macppc/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.54 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.55 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* @@ -29,8 +29,6 @@ * 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> @@ -66,79 +64,53 @@ 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; - unsigned long extoff = 0; - unsigned int fattest; struct buf *bp = NULL; - daddr64_t part_blkno = DOSBBSECTOR; - char *msg = NULL; - char *s; - int dospartoff, cyl, i, ourpart = -1; - int wander = 1, loop = 0; - /* HFS variables */ - int part_cnt, n, hfspartoff; + int i, part_cnt, n, hfspartoff; struct part_map_entry *part; + 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; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - /* DPME (HFS) disklabel */ - + /* First check for a DPME (HFS) disklabel */ bp->b_blkno = 1; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = 1 / lp->d_secpercyl; (*strat)(bp); - - /* if successful, wander through DPME partition table */ if (biowait(bp)) { msg = "DPME partition I/O error"; - goto hfs_done; + goto doslabel; } + /* if successful, wander through DPME partition table */ part = (struct part_map_entry *)bp->b_data; /* if first partition is not valid, assume not HFS/DPME partitioned */ - if (part->pmSig != PART_ENTRY_MAGIC) { + if (part->pmSig != PART_ENTRY_MAGIC) { osdep->macparts[0].pmSig = 0; /* make invalid */ - goto hfs_done; - } + goto doslabel; + } osdep->macparts[0] = *part; part_cnt = part->pmMapBlkCnt; n = 0; for (i = 0; i < part_cnt; i++) { + char *s; + pp = &lp->d_partitions[8+n]; bp->b_blkno = 1+i; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; - bp->b_cylinder = 1+i / lp->d_secpercyl; + bp->b_cylinder = (1+i) / lp->d_secpercyl; (*strat)(bp); - if (biowait(bp)) { msg = "DPME partition I/O error"; - goto hfs_done; + goto doslabel; } part = (struct part_map_entry *)bp->b_data; /* toupper the string, in case caps are different... */ @@ -160,219 +132,42 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), } lp->d_npartitions = MAXPARTITIONS; - /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly) - goto done; + goto doslabel; /* next, dig out disk label */ bp->b_blkno = hfspartoff; - bp->b_cylinder = hfspartoff/lp->d_secpercyl; /* XXX */ + bp->b_cylinder = hfspartoff / lp->d_secpercyl; 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"; goto done; } - goto found_disklabel; - -hfs_done: - /* MBR type disklabel */ - /* do dos partitions in the process of getting disklabel? */ - dospartoff = 0; - cyl = LABELSECTOR / lp->d_secpercyl; - n = 0; - - /* - * 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; + goto realdisklabel; - /* 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) +doslabel: + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) 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"; +realdisklabel: + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) goto done; - } - -found_disklabel: - 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: @@ -380,23 +175,19 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } /* * Write disk label back to device after modification. - * XXX cannot handle OpenBSD partitions in extended partitions! */ 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); @@ -407,79 +198,31 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), /* only write if a valid "OpenBSD" partition type exists */ if (osdep->macparts[1].pmSig == PART_ENTRY_MAGIC) { bp->b_blkno = osdep->macparts[1].pmPyPartStart; - bp->b_cylinder = bp->b_blkno/lp->d_secpercyl; + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; bp->b_bcount = lp->d_secsize; - bp->b_flags = B_BUSY | B_WRITE; - *(struct disklabel *)bp->b_data = *lp; - (*strat)(bp); - error = biowait(bp); - goto done; + goto writeit; } - - /* SHOULD FAIL TO WRITE LABEL IF VALID HFS partition exists - * and no OpenBSD partition exists - */ - error = 1; /* EPERM? */ + error = EIO; goto done; } - /* 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; +writeit: + 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/mips64/include/disklabel.h b/sys/arch/mips64/include/disklabel.h index 7d2fac63bb2..adaf30b4d6f 100644 --- a/sys/arch/mips64/include/disklabel.h +++ b/sys/arch/mips64/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.13 2007/06/07 02:55:12 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd Exp $ */ +/* $OpenBSD: disklabel.h,v 1.14 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -36,50 +35,7 @@ #define LABELSECTOR 1 #define LABELOFFSET 0 - #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ - -/* DOS partition table -- located in boot block */ -#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ -#define DOSPARTOFF 446 -#define DOSACTIVE 0x80 -#define NDOSPART 4 -#define DOSMBR_SIGNATURE 0xaa55 -#define DOSMBR_SIGNATURE_OFF 0x1fe - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) /* SGI */ struct devparms { diff --git a/sys/arch/mips64/mips64/disksubr.c b/sys/arch/mips64/mips64/disksubr.c index 7ef6ea693db..17b97a30e9f 100644 --- a/sys/arch/mips64/mips64/disksubr.c +++ b/sys/arch/mips64/mips64/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.58 2007/06/14 04:56:15 miod Exp $ */ +/* $OpenBSD: disksubr.c,v 1.59 2007/06/17 00:27:29 deraadt Exp $ */ /* * Copyright (c) 1999 Michael Shalayeff @@ -30,16 +30,6 @@ * 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 - */ - -/* - * This disksubr.c module started to take its present form on OpenBSD/alpha - * but it was always thought it should be made completely MI and not need to - * be in that alpha-specific tree at all. - * - * XXX HPUX disklabel is not understood yet. */ #include <sys/param.h> @@ -52,11 +42,8 @@ char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int, int, struct disklabel *, int); -char *readdoslabel(struct buf *, void (*)(struct buf *), - struct disklabel *, struct cpu_disklabel *, int *, int *, int); char *readsgilabel(struct buf *, void (*)(struct buf *), struct disklabel *, struct cpu_disklabel *, int *, int *, int); -void map_sgi_label(struct disklabel *, struct sgilabel *); /* * Try to read a standard BSD disklabel at a certain sector. @@ -67,7 +54,6 @@ readbsdlabel(struct buf *bp, void (*strat)(struct buf *), int spoofonly) { struct disklabel *dlp; - char *msg = NULL; u_int16_t cksum; /* don't read the on-disk label if we are in spoofed-only mode */ @@ -81,38 +67,10 @@ readbsdlabel(struct buf *bp, void (*strat)(struct buf *), (*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"; - return (msg); - } + if (biowait(bp)) + return ("disk label I/O error"); - /* - * If off is negative, search until the end of the sector for - * the label, otherwise, just look at the specific location - * we're given. - */ - dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0)); - do { - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - if (msg == NULL) - msg = "no disk label"; - } else { - cksum = dkcksum(dlp); - if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) { - msg = "disk label corrupted"; - } else { - *lp = *dlp; - msg = NULL; - break; - } - } - if (off >= 0) - break; - dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t)); - } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - - sizeof(*dlp))); - return (msg); + return checkdisklabel(bp->b_data + LABELOFFSET, lp); } /* @@ -130,294 +88,66 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = "no disk label"; - int i; - struct disklabel minilabel, fallbacklabel; - - /* 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"; + char *msg; + + 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; - minilabel = fallbacklabel = *lp; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; msg = readsgilabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) { - /* Fallback alternative XXX valid lp returned? */ - fallbacklabel = *lp; - *lp = minilabel; - } - if (msg) { - msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); - if (msg) { - /* Fallback alternative XXX always valid? */ - fallbacklabel = *lp; - *lp = minilabel; - } - } + if (msg == NULL) + goto done; + + msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); + if (msg == NULL) + goto done; #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 - /* If there was an error, still provide a decent fake one. */ - if (msg) - *lp = fallbacklabel; - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } -/* - * If dos partition table requested, attempt to load it and - * find disklabel inside a DOS partition. Return buffer - * for use in signalling errors if requested. - * - * We would like to check if each MBR has a valid BOOT_MAGIC, but - * we cannot because it doesn't always exist. So.. we assume the - * MBR is valid. - */ -char * -readdoslabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly) - struct buf *bp; - void (*strat)(struct buf *); - struct disklabel *lp; - struct cpu_disklabel *osdep; - int *partoffp; - int *cylp; - int spoofonly; -{ - struct dos_partition dp[NDOSPART], *dp2; - struct partition *pp; - unsigned long extoff = 0; - unsigned int fattest; - daddr64_t part_blkno = DOSBBSECTOR; - char *msg = NULL; - int dospartoff, cyl, i, ourpart = -1; - int wander = 1, n = 0, loop = 0; - - if (lp->d_secpercyl == 0) { - msg = "invalid label, d_secpercyl == 0"; - return (msg); - } - if (lp->d_secsize == 0) { - msg = "invalid label, d_secsize == 0"; - return (msg); - } - - /* 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"; - if (partoffp) - *partoffp = -1; - return (msg); - } - 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: - - /* record the OpenBSD partition's placement for the caller */ - if (partoffp) - *partoffp = dospartoff; - if (cylp) - *cylp = cyl; - - /* next, dig out disk label */ - msg = readbsdlabel(bp, strat, cyl, dospartoff + LABELSECTOR, -1, - lp, spoofonly); - - return (msg); -} +static struct { + int m; + int b; +} maptab[] = { + { 0, FS_BSDFFS}, { 1, FS_SWAP}, { 10, FS_BSDFFS}, + { 3, FS_BSDFFS}, { 4, FS_BSDFFS}, { 5, FS_BSDFFS}, + { 6, FS_BSDFFS}, { 7, FS_BSDFFS}, { 15, FS_OTHER}, + { 9, FS_BSDFFS}, { 2, FS_UNUSED}, { 11, FS_BSDFFS}, + { 12, FS_BSDFFS}, { 13, FS_BSDFFS}, { 14, FS_BSDFFS}, + { 8, FS_BSDFFS} +}; -/* - * - */ char * -readsgilabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly) - struct buf *bp; - void (*strat)(struct buf *); - struct disklabel *lp; - struct cpu_disklabel *osdep; - int *partoffp; - int *cylp; - int spoofonly; +readsgilabel(struct buf *bp, void (*strat)(struct buf *), + struct disklabel *lp, struct cpu_disklabel *osdep, + int *partoffp, int *cylp, int spoofonly) { struct sgilabel *dlp; char *msg = NULL; + int i, *p, cs = 0; int fsoffs = 0; - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) - return (NULL); - - if (partoffp) - *partoffp = -1; - bp->b_blkno = 0; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; @@ -426,63 +156,41 @@ readsgilabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly) /* if successful, locate disk label within block and validate */ if (biowait(bp)) { - if (partoffp) - *partoffp = -1; - return "disk label I/O error"; + msg = "disk label I/O error"; + goto done; } - dlp = (struct sgilabel *)(bp->b_data); + dlp = (struct sgilabel *)(bp->b_data + LABELOFFSET); if (dlp->magic != htobe32(SGILABEL_MAGIC)) { fsoffs = 0; - } else { - int i, *p, cs; - - cs = 0; - p = (int *)dlp; - i = sizeof(struct sgilabel) / sizeof(int); - while(i--) - cs += *p++; - if (cs != 0) - return "sgilabel checksum error"; - - /* Set up partitions i-l if there is no BSD label. */ - lp->d_secsize = dlp->dp.dp_secbytes; - lp->d_nsectors = dlp->dp.dp_secs; - lp->d_ntracks = dlp->dp.dp_trks0; - lp->d_ncylinders = dlp->dp.dp_cyls; - lp->d_interleave = dlp->dp.dp_interleave; - lp->d_npartitions = MAXPARTITIONS; - - map_sgi_label(lp, dlp); - - fsoffs = dlp->partitions[0].first; - if (dlp->partitions[0].blocks == 0) - msg = "no BSD partition"; + goto finished; } - if (msg) - return msg; - - if (partoffp) - *partoffp = fsoffs; + if (dlp->partitions[0].blocks == 0) { + msg = "no BSD partition"; + goto done; + } + fsoffs = dlp->partitions[0].first; - msg = readbsdlabel(bp, strat, 0, fsoffs + LABELSECTOR, - LABELOFFSET, lp, spoofonly); - return msg; -} + if (spoofonly) + goto finished; + + p = (int *)dlp; + i = sizeof(struct sgilabel) / sizeof(int); + while (i--) + cs += *p++; + if (cs != 0) { + msg = "sgilabel checksum error"; + goto done; + } -void -map_sgi_label(struct disklabel *lp, struct sgilabel *dlp) -{ -static struct {int m; int b;} maptab[] = { - { 0, FS_BSDFFS}, { 1, FS_SWAP}, { 10, FS_BSDFFS}, - { 3, FS_BSDFFS}, { 4, FS_BSDFFS}, { 5, FS_BSDFFS}, - { 6, FS_BSDFFS}, { 7, FS_BSDFFS}, { 15, FS_OTHER}, - { 9, FS_BSDFFS}, { 2, FS_UNUSED}, { 11, FS_BSDFFS}, - { 12, FS_BSDFFS}, { 13, FS_BSDFFS}, { 14, FS_BSDFFS}, - { 8, FS_BSDFFS} -}; - int i; + /* Set up partitions i-l if there is no BSD label. */ + lp->d_secsize = dlp->dp.dp_secbytes; + lp->d_nsectors = dlp->dp.dp_secs; + lp->d_ntracks = dlp->dp.dp_trks0; + lp->d_ncylinders = dlp->dp.dp_cyls; + lp->d_interleave = dlp->dp.dp_interleave; + lp->d_npartitions = MAXPARTITIONS; for (i = 0; i < 16; i++) { int bsd = maptab[i].m; @@ -498,6 +206,38 @@ static struct {int m; int b;} maptab[] = { lp->d_partitions[bsd].p_cpg = 16; } } + + lp->d_version = 1; + lp->d_flags = D_VENDOR; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + + +finished: + if (partoffp) + *partoffp = fsoffs; + + if (spoofonly) + goto done; + + bp->b_blkno = fsoffs + LABELSECTOR; + bp->b_cylinder = 0; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) { + msg = "disk label I/O error"; + goto done; + } + + return checkdisklabel(bp->b_data + LABELOFFSET, lp); + +done: + if (dbp) { + dbp->b_flags |= B_INVAL; + brelse(dbp); + } + return (msg); } /* @@ -507,39 +247,36 @@ int writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep) { + int error, partoff = -1, cyl = 0; char *msg = "no disk label"; struct buf *bp = NULL; - struct disklabel dl; - struct cpu_disklabel cdl; - int labeloffset, error, partoff = 0, cyl = 0; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - dl = *lp; - msg = readsgilabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - if (msg) { - dl = *lp; - msg = readdoslabel(bp, strat, &dl, &cdl, &partoff, &cyl, 0); - labeloffset = LABELOFFSET; - } - if (msg) { - if (partoff == -1) { - error = EIO; - goto done; - } + /* find where the disklabel label should be placed */ + if (readsgilabel(bp, strat, &dl, &cdl, &partoff, &cyl, 1) == NULL) + goto writeit; - /* Write it in the regular place with native byte order. */ - labeloffset = LABELOFFSET; - bp->b_blkno = partoff + LABELSECTOR; - bp->b_cylinder = cyl; - bp->b_bcount = lp->d_secsize; - } + if (readdoslabel(bp, strat, &dl, &cdl, &partoff, &cyl, 1) == NULL) + goto writeit; - *(struct disklabel *)(bp->b_data + labeloffset) = *lp; + error = EIO; + goto done; + +writeit: + /* 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 ((error = biowait(bp)) != 0) + goto done; + 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/mvme68k/include/disklabel.h b/sys/arch/mvme68k/include/disklabel.h index 010ad0deefe..3776099140d 100644 --- a/sys/arch/mvme68k/include/disklabel.h +++ b/sys/arch/mvme68k/include/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.8 2003/06/03 21:09:01 deraadt Exp $ */ +/* $OpenBSD: disklabel.h,v 1.9 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1996 Nivas Madhur @@ -34,7 +34,6 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ /* * a cpu_disklabel is a disklabel that the bug (prom) can understand @@ -57,8 +56,10 @@ * around, make sure the various members are properly aligned and the * compiler won't do any additional padding. */ - struct cpu_disklabel { +}; + +struct mvmedisklabel { /* VID */ u_char vid_id[4]; u_char vid_0[16]; diff --git a/sys/arch/mvme68k/mvme68k/disksubr.c b/sys/arch/mvme68k/mvme68k/disksubr.c index d5fd2e96f37..742e420fdcc 100644 --- a/sys/arch/mvme68k/mvme68k/disksubr.c +++ b/sys/arch/mvme68k/mvme68k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.57 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.58 2007/06/17 00:27:29 deraadt Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1995 Dale Rahn. @@ -34,8 +34,8 @@ #include <sys/disklabel.h> #include <sys/disk.h> -void bsdtocpulabel(struct disklabel *, struct cpu_disklabel *); -void cputobsdlabel(struct disklabel *, struct cpu_disklabel *); +void bsdtocpulabel(struct disklabel *, struct mvmedisklabel *); +void cputobsdlabel(struct disklabel *, struct mvmedisklabel *); /* * Attempt to read a disk label from a device @@ -51,51 +51,43 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = NULL; - int error, i; - - /* 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"; - 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; + struct mvmedisklabel *mlp; + int error; + char *msg; - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; + /* don't read the on-disk label if we are in spoofed-only mode */ + if (spoofonly) + goto done; + bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; /* contained in block 0 */ bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); - error = biowait(bp); - if (error == 0) - bcopy(bp->b_data, osdep, sizeof (struct cpu_disklabel)); - if (error) { msg = "disk label read error"; goto done; } + mlp = (struct mvmedisklabel *)bp->b_data; + if (mlp->magic1 != DISKMAGIC || mlp->magic2 != DISKMAGIC) { + msg = "no disk label"; + goto done; + } + + cputobsdlabel(lp, mlp); + if (dkcksum(lp) == 0) + goto done; + msg = "disk label corrupted"; + #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) { msg = NULL; @@ -109,24 +101,11 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), } #endif - if (osdep->magic1 != DISKMAGIC || osdep->magic2 != DISKMAGIC) { - msg = "no disk label"; - goto done; - } - - cputobsdlabel(lp, osdep); - - if (dkcksum(lp) != 0) { - msg = "disk label corrupted"; - goto done; - } - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -145,36 +124,18 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), bp->b_dev = dev; bp->b_blkno = LABELSECTOR; + bp->b_cylinder = 0; /* contained in block 0 */ bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; - bp->b_cylinder = 0; /* contained in block 0 */ (*strat)(bp); - - if ((error = biowait(bp)) != 0) { - /* nothing */ - } else { - bcopy(bp->b_data, osdep, sizeof(struct cpu_disklabel)); - } - - if (error) + if ((error = biowait(bp)) != 0) goto done; - bsdtocpulabel(lp, osdep); + bsdtocpulabel(lp, (struct mvmedisklabel *)bp->b_data); - if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC && - dkcksum(lp) == 0) { - bcopy(osdep, bp->b_data, sizeof(struct cpu_disklabel)); - - /* request no partition relocation by driver on I/O operations */ - bp->b_dev = dev; - bp->b_blkno = 0; /* contained in block 0 */ - bp->b_bcount = lp->d_secsize; - bp->b_flags = B_BUSY | B_WRITE; - bp->b_cylinder = 0; /* contained in block 0 */ - (*strat)(bp); - - error = biowait(bp); - } + bp->b_flags = B_BUSY | B_WRITE; + (*strat)(bp); + error = biowait(bp); done: if (bp) { @@ -185,7 +146,7 @@ done: } void -bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp) +bsdtocpulabel(struct disklabel *lp, struct mvmedisklabel *clp) { char *tmot = "MOTOROLA", *id = "M68K", *mot; int i; @@ -250,7 +211,7 @@ bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp) } void -cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) +cputobsdlabel(struct disklabel *lp, struct mvmedisklabel *clp) { int i; @@ -301,7 +262,6 @@ cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) lp->d_spare[i] = clp->spare[i]; lp->d_magic2 = clp->magic2; - lp->d_checksum = 0; lp->d_npartitions = clp->partitions; lp->d_bbsize = clp->bbsize; lp->d_sbsize = clp->sbsize; @@ -309,10 +269,19 @@ cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) bcopy(clp->vid_4, &lp->d_partitions[0], sizeof(struct partition) * 4); bcopy(clp->cfg_4, &lp->d_partitions[4], sizeof(struct partition) * 12); - if (clp->version == 2) - lp->d_version = 1; - else - lp->d_version = 0; + if (clp->version < 2) { + struct __partitionv0 *v0pp = (struct __partitionv0 *)lp->d_partitions; + struct partition *pp = lp->d_partitions; + + for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) { + pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp-> + p_fsize, v0pp->p_frag); + pp->p_offseth = 0; + pp->p_sizeh = 0; + } + } + lp->d_version = 1; + lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); } diff --git a/sys/arch/mvme88k/include/disklabel.h b/sys/arch/mvme88k/include/disklabel.h index d7ae09fbec9..f70f7a3d739 100644 --- a/sys/arch/mvme88k/include/disklabel.h +++ b/sys/arch/mvme88k/include/disklabel.h @@ -1,4 +1,5 @@ -/* $OpenBSD: disklabel.h,v 1.11 2003/10/11 22:08:57 miod Exp $ */ +/* $OpenBSD: disklabel.h,v 1.12 2007/06/17 00:27:27 deraadt Exp $ */ + /* * Copyright (c) 1996 Nivas Madhur * Copyright (c) 1995 Dale Rahn. @@ -33,15 +34,16 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ /* * Note: this structure is exactly 512 bytes in size. If you move fields * around, make sure the various members are properly aligned and the * compiler won't do any additional padding. */ - struct cpu_disklabel { +}; + +struct mvmedisklabel { /* VID */ u_char vid_id[4]; u_char vid_0[16]; diff --git a/sys/arch/mvme88k/mvme88k/disksubr.c b/sys/arch/mvme88k/mvme88k/disksubr.c index 85dfa0783ac..9750a54032b 100644 --- a/sys/arch/mvme88k/mvme88k/disksubr.c +++ b/sys/arch/mvme88k/mvme88k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.53 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.54 2007/06/17 00:27:29 deraadt Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * Copyright (c) 1995 Dale Rahn. @@ -34,8 +34,8 @@ #include <sys/disklabel.h> #include <sys/disk.h> -void bsdtocpulabel(struct disklabel *, struct cpu_disklabel *); -void cputobsdlabel(struct disklabel *, struct cpu_disklabel *); +void bsdtocpulabel(struct disklabel *, struct mvmedisklabel *); +void cputobsdlabel(struct disklabel *, struct mvmedisklabel *); /* * Attempt to read a disk label from a device @@ -51,51 +51,43 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - char *msg = NULL; - int error, i; - - /* 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"; - 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; + struct mvmedisklabel *mlp; + int error; + char *msg; - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; + /* don't read the on-disk label if we are in spoofed-only mode */ + if (spoofonly) + goto done; + bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; /* contained in block 0 */ bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); - error = biowait(bp); - if (error == 0) - bcopy(bp->b_data, osdep, sizeof (struct cpu_disklabel)); - if (error) { msg = "disk label read error"; goto done; } + mlp = (struct mvmedisklabel *)bp->b_data; + if (mlp->magic1 != DISKMAGIC || mlp->magic2 != DISKMAGIC) { + msg = "no disk label"; + goto done; + } + + cputobsdlabel(lp, mlp); + if (dkcksum(lp) == 0) + goto done; + msg = "disk label corrupted"; + #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) { msg = NULL; @@ -109,24 +101,11 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), } #endif - if (osdep->magic1 != DISKMAGIC || osdep->magic2 != DISKMAGIC) { - msg = "no disk label"; - goto done; - } - - cputobsdlabel(lp, osdep); - - if (dkcksum(lp) != 0) { - msg = "disk label corrupted"; - goto done; - } - done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -144,37 +123,20 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; + /* Read it in, slap the new label in, and write it back out */ bp->b_blkno = LABELSECTOR; + bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; - bp->b_cylinder = 0; /* contained in block 0 */ (*strat)(bp); - - if ((error = biowait(bp)) != 0) { - /* nothing */ - } else { - bcopy(bp->b_data, osdep, sizeof(struct cpu_disklabel)); - } - - if (error) + if ((error = biowait(bp)) != 0) goto done; - bsdtocpulabel(lp, osdep); + bsdtocpulabel(lp, (struct mvmedisklabel *)bp->b_data); - if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC && - dkcksum(lp) == 0) { - bcopy(osdep, bp->b_data, sizeof(struct cpu_disklabel)); - - /* request no partition relocation by driver on I/O operations */ - bp->b_dev = dev; - bp->b_blkno = 0; /* contained in block 0 */ - bp->b_bcount = lp->d_secsize; - bp->b_flags = B_BUSY | B_WRITE; - bp->b_cylinder = 0; /* contained in block 0 */ - (*strat)(bp); - - error = biowait(bp); - } + bp->b_flags = B_BUSY | B_WRITE; + (*strat)(bp); + error = biowait(bp); done: if (bp) { @@ -185,7 +147,7 @@ done: } void -bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp) +bsdtocpulabel(struct disklabel *lp, struct mvmedisklabel *clp) { char *tmot = "MOTOROLA", *id = "M88K", *mot; int i; @@ -250,7 +212,7 @@ bsdtocpulabel(struct disklabel *lp, struct cpu_disklabel *clp) } void -cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) +cputobsdlabel(struct disklabel *lp, struct mvmedisklabel *clp) { int i; @@ -301,7 +263,6 @@ cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) lp->d_spare[i] = clp->spare[i]; lp->d_magic2 = clp->magic2; - lp->d_checksum = 0; lp->d_npartitions = clp->partitions; lp->d_bbsize = clp->bbsize; lp->d_sbsize = clp->sbsize; @@ -309,10 +270,19 @@ cputobsdlabel(struct disklabel *lp, struct cpu_disklabel *clp) bcopy(clp->vid_4, &lp->d_partitions[0], sizeof(struct partition) * 4); bcopy(clp->cfg_4, &lp->d_partitions[4], sizeof(struct partition) * 12); - if (clp->version == 2) - lp->d_version = 1; - else - lp->d_version = 0; + if (clp->version < 2) { + struct __partitionv0 *v0pp = (struct __partitionv0 *)lp->d_partitions; + struct partition *pp = lp->d_partitions; + + for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) { + pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp-> + p_fsize, v0pp->p_frag); + pp->p_offseth = 0; + pp->p_sizeh = 0; + } + } + lp->d_version = 1; + lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); } diff --git a/sys/arch/mvmeppc/include/disklabel.h b/sys/arch/mvmeppc/include/disklabel.h index f1c07fbb4f2..8639d243d34 100644 --- a/sys/arch/mvmeppc/include/disklabel.h +++ b/sys/arch/mvmeppc/include/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.10 2006/10/20 23:47:43 krw Exp $ */ +/* $OpenBSD: disklabel.h,v 1.11 2007/06/17 00:27:27 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -33,56 +33,11 @@ #ifndef _MACHINE_DISKLABEL_H_ #define _MACHINE_DISKLABEL_H_ -#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 */ - -/* MBR partition table */ -#define DOSBBSECTOR 0 /* MBR sector number */ -#define DOSPARTOFF 446 /* Offset of MBR partition table */ -#define NDOSPART 4 /* # of partitions in MBR */ -#define DOSMAGICOFF 510 /* Offset of magic number */ -#define DOSMAGIC 0xaa55 /* Actual magic number */ -#define MBRMAGIC DOSMAGIC -#define DOSMBR_SIGNATURE MBRMAGIC -#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF -#define DOSACTIVE 0x80 - -struct dos_partition { - u_int8_t dp_flag; /* default boot flag */ - u_int8_t dp_shd; /* start head, IsN't Always Meaningful */ - u_int8_t dp_ssect; /* start sector, INAM */ - u_int8_t dp_scyl; /* start cylinder, INAM */ - u_int8_t dp_typ; /* partition type */ - u_int8_t dp_ehd; /* end head, INAM */ - u_int8_t dp_esect; /* end sector, INAM */ - u_int8_t dp_ecyl; /* end cylinder, INAM */ - u_int32_t dp_start; /* absolute start 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 */ +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ 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_ */ diff --git a/sys/arch/mvmeppc/mvmeppc/disksubr.c b/sys/arch/mvmeppc/mvmeppc/disksubr.c index b1307333c6f..502c0840768 100644 --- a/sys/arch/mvmeppc/mvmeppc/disksubr.c +++ b/sys/arch/mvmeppc/mvmeppc/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.50 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.51 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* @@ -29,21 +29,14 @@ * 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> -#define BOOT_MAGIC 0xAA55 -#define BOOT_MAGIC_OFF (DOSPARTOFF+NDOSPART*sizeof(struct dos_partition)) - /* * Attempt to read a disk label from a device * using the indicated strategy routine. @@ -56,7 +49,7 @@ * find disklabel inside a DOS partition. Return buffer * for use in signalling errors if requested. * - * We would like to check if each MBR has a valid BOOT_MAGIC, but + * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but * we cannot because it doesn't always exist. So.. we assume the * MBR is valid. * @@ -66,227 +59,31 @@ 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; - unsigned long extoff = 0; - unsigned int fattest; struct buf *bp = NULL; - daddr64_t part_blkno = DOSBBSECTOR; - 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; /* 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 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) + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) 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"; - 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: @@ -294,7 +91,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -306,72 +102,32 @@ 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) - goto done; - - /* XXX how do we check veracity/bounds of this? */ - bcopy(bp->b_data + DOSPARTOFF, dp, sizeof(dp)); + if (readdoslabel(bp, strat, lp, osdep, &partoff, &cyl, 1) == NULL) + goto writeit; - for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++) - if (letoh32(dp2->dp_size) && dp2->dp_typ == DOSPTYP_OPENBSD) - ourpart = i; + error = EIO; + goto done; - 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; +writeit: + /* 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/sh/include/disklabel.h b/sys/arch/sh/include/disklabel.h index db6ded7f74b..5c38c2bd8c5 100644 --- a/sys/arch/sh/include/disklabel.h +++ b/sys/arch/sh/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.5 2006/10/20 23:47:43 krw Exp $ */ -/* $NetBSD: disklabel.h,v 1.2 2001/11/25 19:02:03 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.6 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1994 Mark Brinicombe. @@ -34,14 +33,6 @@ * 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. - * - * RiscBSD kernel project - * - * disklabel.h - * - * machine specific disk label info - * - * Created : 04/10/94 */ #ifndef _ARM_DISKLABEL_H_ @@ -50,58 +41,6 @@ #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: XX?c */ - -#if 0 -#include <arm/disklabel_acorn.h> -#include <sys/disklabel_mbr.h> -#endif - -/* MBR partition table */ -#define DOSBBSECTOR 0 /* MBR sector number */ -#define DOSPARTOFF 446 /* Offset of MBR partition table */ -#define NDOSPART 4 /* # of partitions in MBR */ -#define DOSMAGICOFF 510 /* Offset of magic number */ -#define DOSMAGIC 0xaa55 /* Actual magic number */ -#define MBRMAGIC DOSMAGIC -#define DOSMBR_SIGNATURE MBRMAGIC -#define DOSMBR_SIGNATURE_OFF DOSMAGICOFF -#define DOSACTIVE 0x80 - - -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 */ - -/* Isolate the relevant bits to get sector and cylinder. */ -#define DPSECT(s) ((s) & 0x3f) -#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) - struct cpu_disklabel { }; diff --git a/sys/arch/solbourne/include/disklabel.h b/sys/arch/solbourne/include/disklabel.h index 2b1ab7758f8..ef20a8f131e 100644 --- a/sys/arch/solbourne/include/disklabel.h +++ b/sys/arch/solbourne/include/disklabel.h @@ -1,3 +1,3 @@ -/* $OpenBSD: disklabel.h,v 1.1 2005/04/19 21:30:17 miod Exp $ */ -/* public domain */ -#include <sparc/disklabel.h>
\ No newline at end of file +/* $OpenBSD: disklabel.h,v 1.2 2007/06/17 00:27:28 deraadt Exp $ */ + +#include <sparc/disklabel.h> diff --git a/sys/arch/sparc/include/disklabel.h b/sys/arch/sparc/include/disklabel.h index 9c9b28b1e1a..d7021e04b65 100644 --- a/sys/arch/sparc/include/disklabel.h +++ b/sys/arch/sparc/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.2 1996/09/12 04:33:27 downsj Exp $ */ -/* $NetBSD: disklabel.h,v 1.4 1995/09/01 17:20:31 pk Exp $ */ +/* $OpenBSD: disklabel.h,v 1.3 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -37,7 +36,6 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 64 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ struct cpu_disklabel { char cd_block[512]; diff --git a/sys/arch/sparc/sparc/disksubr.c b/sys/arch/sparc/sparc/disksubr.c index e4d23d91ea2..c37f39a5bb2 100644 --- a/sys/arch/sparc/sparc/disksubr.c +++ b/sys/arch/sparc/sparc/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.63 2007/06/14 03:41:22 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.64 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.16 1996/04/28 20:25:59 thorpej Exp $ */ /* @@ -46,8 +46,8 @@ #include "cd.h" -static char *disklabel_sun_to_bsd(char *, struct disklabel *); -static int disklabel_bsd_to_sun(struct disklabel *, char *); +static char *disklabel_sun_to_bsd(struct sun_disklabel *, struct disklabel *); +static int disklabel_bsd_to_sun(struct disklabel *, struct sun_disklabel *); static __inline u_int sun_extended_sum(struct sun_disklabel *, void *); #if NCD > 0 @@ -68,39 +68,21 @@ extern void cdstrategy(struct buf *); */ char * readdisklabel(dev_t dev, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *clp, int spoofonly) + struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { - struct buf *bp = NULL; - struct disklabel *dlp; struct sun_disklabel *slp; - char *msg = NULL; - int error, i; - - /* 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"; - 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; - lp->d_bbsize = 8192; - lp->d_sbsize = 64*1024; /* XXX ? */ + struct buf *bp = NULL; + char *msg; - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; + /* + * On sparc64 we check for a CD label first, because our + * CD install media contains both sparc & sparc64 labels. + * We want the sparc64 machine to find the "CD label", not + * the SunOS label, for loading it's kernel. + */ #if NCD > 0 if (strat == cdstrategy) { #if defined(CD9660) @@ -118,47 +100,42 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), } #endif /* NCD > 0 */ - /* obtain buffer to probe drive with */ + /* obtain buffer and initialize it */ bp = geteblk((int)lp->d_secsize); - - /* next, dig out disk label */ bp->b_dev = dev; + + if (spoofonly) + goto doslabel; + bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); - - /* if successful, locate disk label within block and validate */ - error = biowait(bp); - if (error == 0) { - /* Save the whole block in case it has info we need. */ - bcopy(bp->b_data, clp->cd_block, sizeof(clp->cd_block)); - } - if (error) { + if (biowait(bp)) { msg = "disk label read error"; goto done; } - slp = (struct sun_disklabel *)clp->cd_block; + /* XXX because xd(4) & xy(4) still need it */ + bcopy(bp->b_data, osdep->cd_block, sizeof(osdep->cd_block)); + + slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { - msg = disklabel_sun_to_bsd(clp->cd_block, lp); + msg = disklabel_sun_to_bsd(slp, lp); goto done; } - /* Check for a native disk label (PROM can not boot it). */ - dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); - if (dlp->d_magic == DISKMAGIC) { - if (dkcksum(dlp)) { - msg = "disk label corrupted"; - goto done; - } - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; /* struct assignment */ - msg = NULL; + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) goto done; - } +doslabel: + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + + /* A CD9660/UDF label may be on a non-CD drive, so recheck */ #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) { msg = NULL; @@ -171,39 +148,34 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; } #endif - bzero(clp->cd_block, sizeof(clp->cd_block)); - msg = "no disk label"; done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } /* * Write disk label back to device after modification. - * Current label is already in clp->cd_block[] */ int writedisklabel(dev_t dev, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *clp) + struct disklabel *lp, struct cpu_disklabel *osdep) { struct buf *bp = NULL; int error; - error = disklabel_bsd_to_sun(lp, clp->cd_block); + /* obtain buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + error = disklabel_bsd_to_sun(lp, (struct sun_disklabel *)bp->b_data); if (error) goto done; - /* Get a buffer and copy the new label into it. */ - bp = geteblk((int)lp->d_secsize); - bcopy(clp->cd_block, bp->b_data, sizeof(clp->cd_block)); - /* Write out the updated label. */ - bp->b_dev = dev; bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; @@ -272,20 +244,16 @@ sun_extended_sum(struct sun_disklabel *sl, void *end) * The BSD label is cleared out before this is called. */ static char * -disklabel_sun_to_bsd(char *cp, struct disklabel *lp) +disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) { - struct sun_disklabel *sl; struct partition *npp; struct sun_dkpart *spp; int i, secpercyl; - u_short cksum, *sp1, *sp2; - - sl = (struct sun_disklabel *)cp; + u_short cksum = 0, *sp1, *sp2; /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); - cksum = 0; while (sp1 < sp2) cksum ^= *sp1++; if (cksum != 0) @@ -294,6 +262,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; + lp->d_flags = D_VENDOR; memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); lp->d_secsize = 512; @@ -305,7 +274,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) lp->d_secpercyl = secpercyl; if (DL_GETDSIZE(lp) == 0) DL_SETDSIZE(lp, (daddr64_t)secpercyl * sl->sl_ncylinders); - lp->d_version = 1; /* 48 bit addressing */ + lp->d_version = 1; lp->d_sparespercyl = sl->sl_sparespercyl; lp->d_acylinders = sl->sl_acylinders; @@ -396,9 +365,8 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) * Returns zero or error code. */ static int -disklabel_bsd_to_sun(struct disklabel *lp, char *cp) +disklabel_bsd_to_sun(struct disklabel *lp, struct sun_disklabel *sl) { - struct sun_disklabel *sl; struct partition *npp; struct sun_dkpart *spp; int i, secpercyl; @@ -408,8 +376,6 @@ disklabel_bsd_to_sun(struct disklabel *lp, char *cp) if (lp->d_secsize != 512 || lp->d_nsectors == 0 || lp->d_ntracks == 0) return (EINVAL); - sl = (struct sun_disklabel *)cp; - /* Format conversion. */ memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); sl->sl_rpm = lp->d_rpm; diff --git a/sys/arch/sparc64/include/disklabel.h b/sys/arch/sparc64/include/disklabel.h index 1db0609d24e..90be19c3a23 100644 --- a/sys/arch/sparc64/include/disklabel.h +++ b/sys/arch/sparc64/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.2 2001/09/18 21:04:33 jason Exp $ */ -/* $NetBSD: disklabel.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp $ */ +/* $OpenBSD: disklabel.h,v 1.3 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -37,10 +36,8 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 128 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ struct cpu_disklabel { - char cd_block[512]; }; #endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/sparc64/sparc64/disksubr.c b/sys/arch/sparc64/sparc64/disksubr.c index 74ec0a1bf70..ae0475e8e14 100644 --- a/sys/arch/sparc64/sparc64/disksubr.c +++ b/sys/arch/sparc64/sparc64/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.42 2007/06/14 03:41:22 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.43 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk Exp $ */ /* @@ -32,21 +32,15 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/buf.h> -#include <sys/ioccom.h> -#include <sys/device.h> #include <sys/disklabel.h> #include <sys/disk.h> -#include <machine/cpu.h> -#include <machine/autoconf.h> #include <dev/sun/disklabel.h> -#include <dev/sbus/sbusvar.h> - #include "cd.h" -static char *disklabel_sun_to_bsd(char *, struct disklabel *); -static int disklabel_bsd_to_sun(struct disklabel *, char *); +static char *disklabel_sun_to_bsd(struct sun_disklabel *, struct disklabel *); +static int disklabel_bsd_to_sun(struct disklabel *, struct sun_disklabel *); static __inline u_int sun_extended_sum(struct sun_disklabel *, void *); #if NCD > 0 @@ -67,39 +61,21 @@ extern void cdstrategy(struct buf *); */ char * readdisklabel(dev_t dev, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *clp, int spoofonly) + struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { - struct buf *bp = NULL; - struct disklabel *dlp; struct sun_disklabel *slp; - char *msg = NULL; - int error, i; + struct buf *bp = NULL; + 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"; - 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; - lp->d_bbsize = 8192; - lp->d_sbsize = 64*1024; /* XXX ? */ - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + if ((msg = initdisklabel(lp))) goto done; + /* + * On sparc64 we check for a CD label first, because our + * CD install media contains both sparc & sparc64 labels. + * We want the sparc64 machine to find the "CD label", not + * the SunOS label, for loading it's kernel. + */ #if NCD > 0 if (strat == cdstrategy) { #if defined(CD9660) @@ -117,47 +93,39 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), } #endif /* NCD > 0 */ - /* obtain buffer to probe drive with */ + /* obtain buffer and initialize it */ bp = geteblk((int)lp->d_secsize); - - /* next, dig out disk label */ bp->b_dev = dev; + + if (spoofonly) + goto doslabel; + bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); - - /* if successful, locate disk label within block and validate */ - error = biowait(bp); - if (error == 0) { - /* Save the whole block in case it has info we need. */ - bcopy(bp->b_data, clp->cd_block, sizeof(clp->cd_block)); - } - if (error) { + if (biowait(bp)) { msg = "disk label read error"; goto done; } - slp = (struct sun_disklabel *)clp->cd_block; + slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { - msg = disklabel_sun_to_bsd(clp->cd_block, lp); + msg = disklabel_sun_to_bsd(slp, lp); goto done; } - /* Check for a native disk label (PROM can not boot it). */ - dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); - if (dlp->d_magic == DISKMAGIC) { - if (dkcksum(dlp)) { - msg = "disk label corrupted"; - goto done; - } - DL_SETDSIZE(dlp, DL_GETDSIZE(lp)); - *lp = *dlp; /* struct assignment */ - msg = NULL; + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) goto done; - } +doslabel: + msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly); + if (msg == NULL) + goto done; + + /* A CD9660/UDF label may be on a non-CD drive, so recheck */ #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) { msg = NULL; @@ -170,39 +138,34 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; } #endif - bzero(clp->cd_block, sizeof(clp->cd_block)); - msg = "no disk label"; done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } /* * Write disk label back to device after modification. - * Current label is already in clp->cd_block[] */ int writedisklabel(dev_t dev, void (*strat)(struct buf *), - struct disklabel *lp, struct cpu_disklabel *clp) + struct disklabel *lp, struct cpu_disklabel *osdep) { struct buf *bp = NULL; int error; - error = disklabel_bsd_to_sun(lp, clp->cd_block); + /* obtain buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + error = disklabel_bsd_to_sun(lp, (struct sun_disklabel *)bp->b_data); if (error) goto done; - /* Get a buffer and copy the new label into it. */ - bp = geteblk((int)lp->d_secsize); - bcopy(clp->cd_block, bp->b_data, sizeof(clp->cd_block)); - /* Write out the updated label. */ - bp->b_dev = dev; bp->b_blkno = LABELSECTOR; bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; @@ -271,20 +234,16 @@ sun_extended_sum(struct sun_disklabel *sl, void *end) * The BSD label is cleared out before this is called. */ static char * -disklabel_sun_to_bsd(char *cp, struct disklabel *lp) +disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) { - struct sun_disklabel *sl; struct partition *npp; struct sun_dkpart *spp; int i, secpercyl; - u_short cksum, *sp1, *sp2; - - sl = (struct sun_disklabel *)cp; + u_short cksum = 0, *sp1, *sp2; /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); - cksum = 0; while (sp1 < sp2) cksum ^= *sp1++; if (cksum != 0) @@ -293,6 +252,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; + lp->d_flags = D_VENDOR; memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); lp->d_secsize = 512; @@ -304,7 +264,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) lp->d_secpercyl = secpercyl; if (DL_GETDSIZE(lp) == 0) DL_SETDSIZE(lp, (daddr64_t)secpercyl * sl->sl_ncylinders); - lp->d_version = 1; /* 48 bit addressing */ + lp->d_version = 1; lp->d_sparespercyl = sl->sl_sparespercyl; lp->d_acylinders = sl->sl_acylinders; @@ -395,9 +355,8 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp) * Returns zero or error code. */ static int -disklabel_bsd_to_sun(struct disklabel *lp, char *cp) +disklabel_bsd_to_sun(struct disklabel *lp, struct sun_disklabel *sl) { - struct sun_disklabel *sl; struct partition *npp; struct sun_dkpart *spp; int i, secpercyl; @@ -407,8 +366,6 @@ disklabel_bsd_to_sun(struct disklabel *lp, char *cp) if (lp->d_secsize != 512 || lp->d_nsectors == 0 || lp->d_ntracks == 0) return (EINVAL); - sl = (struct sun_disklabel *)cp; - /* Format conversion. */ memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); sl->sl_rpm = lp->d_rpm; diff --git a/sys/arch/vax/include/disklabel.h b/sys/arch/vax/include/disklabel.h index be218718271..cae29811e77 100644 --- a/sys/arch/vax/include/disklabel.h +++ b/sys/arch/vax/include/disklabel.h @@ -1,5 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.7 2001/12/06 23:47:28 miod Exp $ */ -/* $NetBSD: disklabel.h,v 1.4 1997/03/09 15:55:58 ragge Exp $ */ +/* $OpenBSD: disklabel.h,v 1.8 2007/06/17 00:27:28 deraadt Exp $ */ /* * Copyright (c) 1994 Christopher G. Demetriou @@ -37,12 +36,10 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 64 /* offset of label in sector */ #define MAXPARTITIONS 16 /* number of partitions */ -#define RAW_PART 2 /* raw partition: xx?c */ -/* Just a dummy */ #ifndef _LOCORE struct cpu_disklabel { - /* EMPTY */ }; + #endif #endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/vax/vax/disksubr.c b/sys/arch/vax/vax/disksubr.c index 7a49d613ce9..b7a5e1af284 100644 --- a/sys/arch/vax/vax/disksubr.c +++ b/sys/arch/vax/vax/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.51 2007/06/14 03:37:23 deraadt Exp $ */ +/* $OpenBSD: disksubr.c,v 1.52 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1999/06/30 18:48:06 ragge Exp $ */ /* @@ -28,8 +28,6 @@ * 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> @@ -63,37 +61,17 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly) { struct buf *bp = NULL; - struct disklabel *dlp; - char *msg = NULL; - int i; - - /* 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"; - 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; - lp->d_bbsize = 8192; - lp->d_sbsize = 64 * 1024; - - /* don't read the on-disk label if we are in spoofed-only mode */ - if (spoofonly) + char *msg; + + if ((msg = initdisklabel(lp))) goto done; bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; + + if (spoofonly) + goto done; + bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; @@ -101,26 +79,24 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), (*strat)(bp); if (biowait(bp)) { msg = "I/O error"; - } else { - dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); - if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { - 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; - } + goto done; } + msg = checkdisklabel(bp->b_data + LABELOFFSET, lp); + if (msg == NULL) + goto done; + #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: @@ -128,7 +104,6 @@ done: bp->b_flags |= B_INVAL; brelse(bp); } - disklabeltokernlabel(lp); return (msg); } @@ -145,9 +120,11 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), int error = 0; bp = geteblk((int)lp->d_secsize); - bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART); + bp->b_dev = dev; + + /* Read it in, slap the new label in, and write it back out */ bp->b_blkno = LABELSECTOR; - bp->b_cylinder = LABELSECTOR / lp->d_secpercyl; + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; (*strat)(bp); @@ -155,7 +132,7 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), goto done; dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); - bcopy(lp, dlp, sizeof(struct disklabel)); + *dlp = *lp; bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); error = biowait(bp); diff --git a/sys/arch/zaurus/include/disklabel.h b/sys/arch/zaurus/include/disklabel.h index 7e63a238746..0c0642c339a 100644 --- a/sys/arch/zaurus/include/disklabel.h +++ b/sys/arch/zaurus/include/disklabel.h @@ -1,4 +1,3 @@ -/* $OpenBSD: disklabel.h,v 1.1 2004/12/31 00:04:35 drahn Exp $ */ -/* $NetBSD: disklabel.h,v 1.3 2001/11/25 15:55:55 thorpej Exp $ */ +/* $OpenBSD: disklabel.h,v 1.2 2007/06/17 00:27:28 deraadt Exp $ */ #include <arm/disklabel.h> diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index 5e2f9064225..40c548d4a76 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_disk.c,v 1.59 2007/06/10 16:37:09 deraadt Exp $ */ +/* $OpenBSD: subr_disk.c,v 1.60 2007/06/17 00:27:30 deraadt Exp $ */ /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */ /* @@ -181,67 +181,373 @@ dkcksum(struct disklabel *lp) return (sum); } +char * +initdisklabel(struct disklabel *lp) +{ + int i; + + /* 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) + return ("invalid geometry"); + 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; + lp->d_bbsize = 8192; + lp->d_sbsize = 64*1024; /* XXX ? */ + return (NULL); +} + /* - * Convert an on-disk disklabel to a kernel disklabel, converting versions - * as required and applying constraints that kernel disklabels are guaranteed - * to satisfy. + * Check an incoming block to make sure it is a disklabel, convert it to + * a newer version if needed, etc etc. */ -void -disklabeltokernlabel(struct disklabel *lp) +char * +checkdisklabel(void *rlp, struct disklabel *lp) { - struct __partitionv0 *v0pp = (struct __partitionv0 *)lp->d_partitions; - struct partition *pp = lp->d_partitions; - int i, oversion = lp->d_version, changed = 0, okbefore = 0; + struct disklabel *dlp = rlp; + struct __partitionv0 *v0pp; + struct partition *pp; + daddr64_t disksize; + char *msg = NULL; + int i; + + if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) + msg = "no disk label"; + else if (dlp->d_npartitions > MAXPARTITIONS) + msg = "unreasonable partition count"; + else if (dkcksum(dlp) != 0) + msg = "disk label corrupted"; + + if (msg) { + u_int16_t *start, *end, sum = 0; + + /* If it is byte-swapped, attempt to convert it */ + if (swap32(dlp->d_magic) != DISKMAGIC || + swap32(dlp->d_magic2) != DISKMAGIC || + swap16(dlp->d_npartitions) > MAXPARTITIONS) + return (msg); + + /* + * Need a byte-swap aware dkcksum varient + * inlined, because dkcksum uses a sub-field + */ + start = (u_int16_t *)dlp; + end = (u_int16_t *)&dlp->d_partitions[ + swap16(dlp->d_npartitions)]; + while (start < end) + sum ^= *start++; + if (sum != 0) + return (msg); + + dlp->d_magic = swap32(dlp->d_magic); + dlp->d_type = swap16(dlp->d_type); + dlp->d_subtype = swap16(dlp->d_subtype); + + /* d_typename and d_packname are strings */ + + dlp->d_secsize = swap32(dlp->d_secsize); + dlp->d_nsectors = swap32(dlp->d_nsectors); + dlp->d_ntracks = swap32(dlp->d_ntracks); + dlp->d_ncylinders = swap32(dlp->d_ncylinders); + dlp->d_secpercyl = swap32(dlp->d_secpercyl); + dlp->d_secperunit = swap32(dlp->d_secperunit); + + dlp->d_sparespertrack = swap16(dlp->d_sparespertrack); + dlp->d_sparespercyl = swap16(dlp->d_sparespercyl); + + dlp->d_acylinders = swap32(dlp->d_acylinders); + + dlp->d_rpm = swap16(dlp->d_rpm); + dlp->d_interleave = swap16(dlp->d_interleave); + dlp->d_trackskew = swap16(dlp->d_trackskew); + dlp->d_cylskew = swap16(dlp->d_cylskew); + dlp->d_headswitch = swap32(dlp->d_headswitch); + dlp->d_trkseek = swap32(dlp->d_trkseek); + dlp->d_flags = swap32(dlp->d_flags); + + for (i = 0; i < NDDATA; i++) + dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]); + + dlp->d_secperunith = swap16(dlp->d_secperunith); + dlp->d_version = swap16(dlp->d_version); + + for (i = 0; i < NSPARE; i++) + dlp->d_spare[i] = swap32(dlp->d_spare[i]); + + dlp->d_magic2 = swap32(dlp->d_magic2); + dlp->d_checksum = swap16(dlp->d_checksum); + + dlp->d_npartitions = swap16(dlp->d_npartitions); + dlp->d_bbsize = swap32(dlp->d_bbsize); + dlp->d_sbsize = swap32(dlp->d_sbsize); + + for (i = 0; i < MAXPARTITIONS; i++) { + pp = &dlp->d_partitions[i]; + pp->p_size = swap32(pp->p_size); + pp->p_offset = swap32(pp->p_offset); + if (dlp->d_version == 0) { + v0pp = (struct __partitionv0 *)pp; + v0pp->p_fsize = swap32(v0pp->p_fsize); + } else { + pp->p_offseth = swap16(pp->p_offseth); + pp->p_sizeh = swap16(pp->p_sizeh); + } + pp->p_cpg = swap16(pp->p_cpg); + } + + dlp->d_checksum = 0; + dlp->d_checksum = dkcksum(dlp); + msg = NULL; + } + + /* XXX should verify lots of other fields and whine a lot */ + + if (msg) + return (msg); + + /* Initial passed in lp contains the real disk size */ + disksize = DL_GETDSIZE(lp); - if (dkcksum(lp) == 0) - okbefore = 1; + if (lp != dlp) + *lp = *dlp; - if (oversion == 0) { + if (lp->d_version == 0) { lp->d_version = 1; lp->d_secperunith = 0; - changed = 1; - } - for (i = 0; i < MAXPARTITIONS; i++, pp++, v0pp++) { - if (oversion == 0) { + v0pp = (struct __partitionv0 *)lp->d_partitions; + pp = lp->d_partitions; + for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) { pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp-> p_fsize, v0pp->p_frag); pp->p_offseth = 0; pp->p_sizeh = 0; } + } -#ifdef notyet - /* XXX this should not be here */ - - /* In a V1 label no partition extends past DL_GETSIZE(lp) - 1. */ - if (DL_GETPOFFSET(pp) > DL_GETDSIZE(lp)) { - pp->p_fstype = FS_UNUSED; - DL_SETPSIZE(pp, 0); - DL_SETPOFFSET(pp, 0); - } else if (DL_GETPOFFSET(pp) + DL_GETPSIZE(pp) > DL_GETDSIZE(lp)) { - daddr64_t sz; - - printf("%lld %lld %lld\n", - DL_GETPOFFSET(pp), DL_GETPSIZE(pp), - DL_GETPOFFSET(pp) + DL_GETPSIZE(pp), - DL_GETDSIZE(lp)); - pp->p_fstype = FS_UNUSED; - sz = DL_GETDSIZE(lp) - DL_GETPOFFSET(pp); - DL_SETPSIZE(pp, sz); - } +#ifdef noonecares + if (DL_GETDSIZE(lp) != disksize) + printf("new disklabel disk size different %lld != %lld\n", + DL_GETDSIZE(lp), disksize); #endif - } + DL_SETDSIZE(lp, disksize); - /* XXX this should not be here */ - if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0) { - DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); - DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); - changed = 1; + if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != DL_GETDSIZE(lp)) + printf("new disklabel raw disk size different %lld != %lld\n", + DL_GETPSIZE(&lp->d_partitions[RAW_PART]), DL_GETDSIZE(lp)); + DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); + + if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0) + printf("new disklabel raw disk offset different %lld != %lld\n", + DL_GETPOFFSET(&lp->d_partitions[RAW_PART]), 0); + DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); + + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + return (msg); +} + +/* + * If dos partition table requested, attempt to load it and + * find disklabel inside a DOS partition. Return buffer + * for use in signalling errors if requested. + * + * We would like to check if each MBR has a valid BOOT_MAGIC, but + * we cannot because it doesn't always exist. So.. we assume the + * MBR is valid. + */ +char * +readdoslabel(struct buf *bp, void (*strat)(struct buf *), + struct disklabel *lp, struct cpu_disklabel *osdep, + int *partoffp, int *cylp, int spoofonly) +{ + struct dos_partition dp[NDOSPART], *dp2; + u_int32_t extoff = 0; + daddr64_t part_blkno = DOSBBSECTOR; + int dospartoff = 0, cyl, i, ourpart = -1; + int wander = 1, n = 0, loop = 0; + + if (lp->d_secpercyl == 0) + return ("invalid label, d_secpercyl == 0"); + if (lp->d_secsize == 0) + return ("invalid label, d_secsize == 0"); + + /* do DOS partitions in the process of getting disklabel? */ + cyl = DOS_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 (biowait(bp)) { +/*wrong*/ if (partoffp) +/*wrong*/ *partoffp = -1; + return ("dos partition I/O error"); + } + + 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); + + /* found our OpenBSD partition, finish up */ + if (partoffp) + goto notfat; + + 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++) { + struct partition *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; + } + } } - if (changed && okbefore) { - lp->d_checksum = 0; - lp->d_checksum = dkcksum(lp); + lp->d_npartitions = MAXPARTITIONS; + + if (n == 0 && part_blkno == DOSBBSECTOR) { + u_int16_t fattest; + + /* 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: + + /* record the OpenBSD partition's placement for the caller */ + if (partoffp) + *partoffp = dospartoff; + if (cylp) + *cylp = cyl; + + /* don't read the on-disk label if we are in spoofed-only mode */ + if (spoofonly) + return (NULL); + + bp->b_blkno = dospartoff + DOS_LABELSECTOR; + bp->b_cylinder = cyl; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) + return ("disk label I/O error"); + + /* sub-MBR disklabels are always at a LABELOFFSET of 0 */ + return checkdisklabel(bp->b_data + 0, lp); } /* diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index 7f01f32096e..26c3bbdf008 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.36 2007/06/06 16:42:07 deraadt Exp $ */ +/* $OpenBSD: disklabel.h,v 1.37 2007/06/17 00:27:29 deraadt Exp $ */ /* $NetBSD: disklabel.h,v 1.41 1996/05/10 23:07:37 mark Exp $ */ /* @@ -62,6 +62,7 @@ */ #define DISKUNIT(dev) (minor(dev) / MAXPARTITIONS) #define DISKPART(dev) (minor(dev) % MAXPARTITIONS) +#define RAW_PART 2 /* 'c' partition */ #define DISKMINOR(unit, part) \ (((unit) * MAXPARTITIONS) + (part)) #define MAKEDISKDEV(maj, unit, part) \ @@ -352,6 +353,7 @@ static char *fstypesnames[] = { * flags shared by various drives: */ #define D_BADSECT 0x04 /* supports bad sector forw. */ +#define D_VENDOR 0x08 /* vendor disklabel */ /* * Drive data for SMD. @@ -395,11 +397,62 @@ struct partinfo { struct partition *part; }; +/* DOS partition table -- located at start of some disks. */ +#define DOS_LABELSECTOR 1 +#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ +#define DOSPARTOFF 446 +#define DOSDISKOFF 444 +#define NDOSPART 4 +#define DOSACTIVE 0x80 /* active partition */ + +#define DOSMBR_SIGNATURE (0xaa55) +#define DOSMBR_SIGNATURE_OFF (0x1fe) + +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 */ +}; + +/* Isolate the relevant bits to get sector and cylinder. */ +#define DPSECT(s) ((s) & 0x3f) +#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) + +/* 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; (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; + #ifdef _KERNEL void diskerr(struct buf *, char *, char *, int, int, struct disklabel *); void disksort(struct buf *, struct buf *); u_int dkcksum(struct disklabel *); -void disklabeltokernlabel(struct disklabel *); +char *initdisklabel(struct disklabel *); +char *checkdisklabel(void *, struct disklabel *); int setdisklabel(struct disklabel *, struct disklabel *, u_int, struct cpu_disklabel *); char *readdisklabel(dev_t, void (*)(struct buf *), struct disklabel *, @@ -408,6 +461,8 @@ int writedisklabel(dev_t, void (*)(struct buf *), struct disklabel *, struct cpu_disklabel *); int bounds_check_with_label(struct buf *, struct disklabel *, struct cpu_disklabel *, int); +char *readdoslabel(struct buf *, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int *, int *, int); #ifdef CD9660 int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp); |