From 54c7241bd31ddd11e8a92f77a69679422843f96e Mon Sep 17 00:00:00 2001 From: "Jordan K. Hubbard" Date: Thu, 27 Oct 1994 20:45:13 +0000 Subject: [PATCH] Julian Elischer's disklabel fixes. --- sys/amd64/amd64/machdep.c | 3 +- sys/conf/files.i386 | 3 +- sys/dev/fdc/fdc.c | 8 +- sys/dev/mcd/mcd.c | 3 +- sys/i386/conf/files.i386 | 3 +- sys/i386/i386/machdep.c | 3 +- sys/i386/isa/fd.c | 8 +- sys/i386/isa/mcd.c | 3 +- sys/i386/isa/readMBR.c | 232 +++++++++++++++++++++++++++++++++++++ sys/i386/isa/wd.c | 27 ++--- sys/isa/fd.c | 8 +- sys/kern/subr_disklabel.c | 232 +++++++++++++++++++++++-------------- sys/scsi/cd.c | 6 +- sys/scsi/sd.c | 9 +- sys/sys/disklabel.h | 42 ++++++- sys/sys/diskmbr.h | 42 ++++++- sys/sys/diskpc98.h | 42 ++++++- sys/ufs/ufs/ufs_disksubr.c | 232 +++++++++++++++++++++++-------------- sys/ufs/ufs/ufs_extern.h | 10 +- 19 files changed, 687 insertions(+), 229 deletions(-) create mode 100644 sys/i386/isa/readMBR.c diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index cfedceb21d06..49dbd471f44b 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.80 1994/10/25 08:58:33 davidg Exp $ + * $Id: machdep.c,v 1.81 1994/10/26 18:35:02 jkh Exp $ */ #include "npx.h" @@ -1563,7 +1563,6 @@ Debugger(const char *msg) #include #define b_cylin b_resid -#define dkpart(dev) (minor(dev) & 7) /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. Adjust transfer diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 2e76e02b1792..c0cdb8a27852 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.54 1994/10/13 20:19:11 sos Exp $ +# $Id: files.i386,v 1.55 1994/10/26 19:19:12 jkh Exp $ # i386/apm/apm.c optional apm device-driver i386/apm/apm_setup.s optional apm @@ -112,6 +112,7 @@ i386/isa/sound/uart6850.c optional snd device-driver i386/isa/spkr.c optional speaker i386/isa/tw.c optional tw device-driver i386/isa/ultra14f.c optional uha device-driver +i386/isa/readMBR.c standard i386/isa/wd.c optional wd device-driver i386/isa/wt.c optional wt device-driver i386/isa/pcvt/pcvt_drv.c optional vt device-driver diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index a000acf89420..e06ac4aab450 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -40,7 +40,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.36 1994/10/21 16:58:50 joerg Exp $ + * $Id: fd.c,v 1.37 1994/10/23 21:27:12 wollman Exp $ * */ @@ -1522,7 +1522,7 @@ fdioctl(dev, cmd, addr, flag, p) dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; - if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) + if (readdisklabel(dev, fdstrategy, dl, NULL, 0) == NULL) error = 0; else error = EINVAL; @@ -1550,11 +1550,11 @@ fdioctl(dev, cmd, addr, flag, p) dl = (struct disklabel *)addr; if ((error = - setdisklabel ((struct disklabel *)buffer, dl, 0, NULL))) + setdisklabel ((struct disklabel *)buffer, dl, 0))) break; error = writedisklabel(dev, fdstrategy, - (struct disklabel *)buffer, NULL); + (struct disklabel *)buffer); break; case FD_FORM: diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c index e27f600d32c6..a6d4bbb8ad46 100644 --- a/sys/dev/mcd/mcd.c +++ b/sys/dev/mcd/mcd.c @@ -39,7 +39,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mcd.c,v 1.25 1994/09/14 20:28:25 ache Exp $ + * $Id: mcd.c,v 1.26 1994/10/23 21:27:29 wollman Exp $ */ static char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; @@ -483,7 +483,6 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0); else { return setdisklabel(&cd->dlabel, (struct disklabel *) addr, - 0, 0); } case DIOCWLABEL: diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 2e76e02b1792..c0cdb8a27852 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.54 1994/10/13 20:19:11 sos Exp $ +# $Id: files.i386,v 1.55 1994/10/26 19:19:12 jkh Exp $ # i386/apm/apm.c optional apm device-driver i386/apm/apm_setup.s optional apm @@ -112,6 +112,7 @@ i386/isa/sound/uart6850.c optional snd device-driver i386/isa/spkr.c optional speaker i386/isa/tw.c optional tw device-driver i386/isa/ultra14f.c optional uha device-driver +i386/isa/readMBR.c standard i386/isa/wd.c optional wd device-driver i386/isa/wt.c optional wt device-driver i386/isa/pcvt/pcvt_drv.c optional vt device-driver diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index cfedceb21d06..49dbd471f44b 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.80 1994/10/25 08:58:33 davidg Exp $ + * $Id: machdep.c,v 1.81 1994/10/26 18:35:02 jkh Exp $ */ #include "npx.h" @@ -1563,7 +1563,6 @@ Debugger(const char *msg) #include #define b_cylin b_resid -#define dkpart(dev) (minor(dev) & 7) /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. Adjust transfer diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index a000acf89420..e06ac4aab450 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -40,7 +40,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.36 1994/10/21 16:58:50 joerg Exp $ + * $Id: fd.c,v 1.37 1994/10/23 21:27:12 wollman Exp $ * */ @@ -1522,7 +1522,7 @@ fdioctl(dev, cmd, addr, flag, p) dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; - if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) + if (readdisklabel(dev, fdstrategy, dl, NULL, 0) == NULL) error = 0; else error = EINVAL; @@ -1550,11 +1550,11 @@ fdioctl(dev, cmd, addr, flag, p) dl = (struct disklabel *)addr; if ((error = - setdisklabel ((struct disklabel *)buffer, dl, 0, NULL))) + setdisklabel ((struct disklabel *)buffer, dl, 0))) break; error = writedisklabel(dev, fdstrategy, - (struct disklabel *)buffer, NULL); + (struct disklabel *)buffer); break; case FD_FORM: diff --git a/sys/i386/isa/mcd.c b/sys/i386/isa/mcd.c index e27f600d32c6..a6d4bbb8ad46 100644 --- a/sys/i386/isa/mcd.c +++ b/sys/i386/isa/mcd.c @@ -39,7 +39,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mcd.c,v 1.25 1994/09/14 20:28:25 ache Exp $ + * $Id: mcd.c,v 1.26 1994/10/23 21:27:29 wollman Exp $ */ static char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; @@ -483,7 +483,6 @@ MCD_TRACE("ioctl called 0x%x\n",cmd,0,0,0); else { return setdisklabel(&cd->dlabel, (struct disklabel *) addr, - 0, 0); } case DIOCWLABEL: diff --git a/sys/i386/isa/readMBR.c b/sys/i386/isa/readMBR.c new file mode 100644 index 000000000000..4165d214ed0c --- /dev/null +++ b/sys/i386/isa/readMBR.c @@ -0,0 +1,232 @@ +/* + * + * THIS SOFTWARE IS PROVIDED BY THE WRITERS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE WRITERS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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. + * + * written by julian elischer (julian@tfs.com) + * + * @(#)readMBR.c 8.5 (tfs) 1/21/94 + * $Id: readMBR.c,v 1.5 1994/10/17 02:31:33 phk Exp $ + */ + +#include +#include +#include +#include + +#define b_cylinder b_resid + +/* + * Attempt to read a machine-type dependent Device partitioning table + * In this case a PC BIOS MBR. + * Destroys the original disklabel if it finds an MBR, so you'd better + * know what you're doing. It assumes that the label you've given it + * Is the one that controls the device, so that it can fiddle with it + * to make sure it's reading absolute sectors. + * On exit: + * Leaves the disklabel set up with the various partitions + * in the last 4 entries, + * the A partition pointing to the BSD part + * the C partition set as the BSD partition, (read the disklabel from there) and + * the D partition set as the whole disk for beating up + * will also give you a copy of the machine dependent table if you ask.. + * returns 0 for success, + * On failure, restores the disklabel and returns a messages pointer. + */ +char * +readMBRtolabel(dev, strat, lp, dp, cyl) + dev_t dev; + void (*strat)(); + register struct disklabel *lp; + struct dos_partition *dp; + int *cyl; +{ + register struct buf *bp; + struct disklabel *dlp; + struct disklabel labelsave; + char *msg = NULL; + int i; + int pseudopart = 4; /* we fill in pseudoparts from e through h*/ + int seenBSD = 0; + + /* + * Save a copy of the disklabel in case we return with an error + */ + bcopy(lp,&labelsave,sizeof(labelsave)); + + /* + * Set the disklabel to some useable partitions in case it's rubbish + */ + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + lp->d_npartitions = 4; + for (i=0; id_partitions[i].p_offset = 0; + lp->d_partitions[i].p_size = 0; + } + lp->d_partitions[RAWPART].p_size = DOSBBSECTOR + 1; /* start low */ + strcpy(lp->d_packname,"MBR based label"); /* Watch the length ! */ + + /* + * Get a buffer and get ready to read the MBR + */ + bp = geteblk((int)lp->d_secsize); + /* read master boot record */ + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), RAWPART)); + 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 successful, wander through dos partition table */ + if ( biowait(bp)) { + msg = "dos partition I/O error"; + goto bad; + } else { + /* + * If there seems to be BIOS bootblock and partition table + * in that block, then try interpret it, otherwise + * give up and use whatever we have synthesised so far + */ + if ((*(bp->b_un.b_addr + 510) != (char) 0x55) + ||(*(bp->b_un.b_addr + 511) != (char) 0xaa)) { + msg = "Disk has no Fdisk partitions"; + goto bad; + } + + if(dp) { /* if they asked for a copy, give it to them */ + bcopy(bp->b_un.b_addr + DOSPARTOFF, dp, + NDOSPART * sizeof(*dp)); + } + dp = (struct dos_partition *)(bp->b_un.b_addr + DOSPARTOFF); + /* + * We have a DOS MBR.. + * We set up the last 4 partitions in the + * disklabel to reflect the DOS partitions + * In case we never find a disklabel, in which + * case this information will be all we have + * but it might be all we need to access a DOS + * partition. + */ + for (i = 0; i < NDOSPART; i++, dp++,pseudopart++) { + + if (!dp->dp_size) + continue; + /* + * Set this DOS part into the disklabel + */ + lp->d_partitions[pseudopart].p_size = + dp->dp_size; + lp->d_partitions[pseudopart].p_offset = + dp->dp_start; + + /* + * make sure the D part can hold it all + */ + if((dp->dp_start + dp->dp_size) + > lp->d_partitions[3].p_size) { + lp->d_partitions[3].p_size + = (dp->dp_start + dp->dp_size); + } + + /* + * If we haven't seen a *BSD partition then + * check if this is a valid part.. + * if it is it may be the best we are going to + * to see, so take note of it to deduce a + * geometry in case we never find a disklabel. + */ + switch(dp->dp_typ) { + case DOSPTYP_386BSD: + /* + * at a pinch we could throw + * a FFS on here + */ + lp->d_partitions[pseudopart].p_fstype + = FS_BSDFFS; + /* + * Only get a disklabel from the + * first one we see.. + */ + if (seenBSD == 0) { + /* + * If it IS our part, then we + * need sector address for + * SCSI/IDE, cylinder for + * ESDI/ST506/RLL + */ + seenBSD = 1; + *cyl = DPCYL(dp->dp_scyl, + dp->dp_ssect); + + /* + * Note which part we are in (?) + */ + lp->d_subtype &= ~3; + lp->d_subtype |= i & 3; + lp->d_subtype + |= DSTYPE_INDOSPART; + + /* + * update disklabel with + * details for reading the REAL + * disklabel it it exists + */ + lp->d_partitions[OURPART].p_size = + dp->dp_size; + lp->d_partitions[OURPART].p_offset = + dp->dp_start; + } + break; + case 0xB7: /* BSDI (?)*//* doubtful */ + lp->d_partitions[pseudopart].p_fstype + = FS_BSDFFS; + break; + case 1: + case 4: + case 6: + case 0xF2: + lp->d_partitions[pseudopart].p_fstype + = FS_MSDOS; + break; + } + + /* + * Try deduce the geometry, working + * on the principle that this + * partition PROBABLY ends on a + * cylinder boundary. + * This is really a kludge, but we are + * forced into it by the PC's design. + * If we've seen a 386bsd part, + * believe it and check no further. + */ + if (seenBSD) continue; + lp->d_ntracks = dp->dp_ehd + 1; + lp->d_nsectors = DPSECT(dp->dp_esect); + lp->d_secpercyl = lp->d_ntracks * + lp->d_nsectors; + } + lp->d_npartitions = 8; + } + bp->b_flags = B_INVAL | B_AGE; + brelse(bp); + return 0; +bad: + bcopy(&labelsave,lp,sizeof(labelsave)); + bp->b_flags = B_INVAL | B_AGE; + brelse(bp); + return msg; +} + + diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index 8cc7460c0dd0..30c990d72733 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -37,7 +37,7 @@ static int wdtest = 0; * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.56 1994/10/23 21:27:40 wollman Exp $ + * $Id: wd.c,v 1.57 1994/10/27 05:39:12 phk Exp $ */ /* TODO: @@ -271,8 +271,6 @@ struct isa_driver wdcdriver = { wdprobe, wdattach, "wdc", }; -extern char *readdisklabel(); - /* * Probe for controller. */ @@ -993,14 +991,9 @@ wdopen(dev_t dev, int flags, int fmt, struct proc *p) save_label = du->dk_dd; du->dk_dd.d_partitions[WDRAW].p_offset = 0; du->dk_dd.d_partitions[WDRAW].p_size = 0x7fffffff;/* XXX */ -#define WDSTRATEGY ((int (*)(struct buf *)) wdstrategy) /* XXX */ msg = readdisklabel(makewddev(major(dev), lunit, WDRAW), - WDSTRATEGY, &du->dk_dd, + wdstrategy, &du->dk_dd, du->dk_dospartitions, &du->dk_bad); -/* - msg = readdisklabel(makewddev(major(dev), lunit, WDRAW), - WDSTRATEGY, &du->dk_dd); -*/ du->dk_flags &= ~DKFL_LABELLING; if (msg != NULL) { du->dk_dd = save_label; @@ -1437,8 +1430,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag) du->dk_flags & DKFL_BSDLABEL ? du->dk_openpart : #endif - 0, - du->dk_dospartitions); + 0); if (error == 0) { du->dk_flags |= DKFL_BSDLABEL; wdwsetctlr(du); /* XXX - check */ @@ -1463,8 +1455,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag) du->dk_flags & DKFL_BSDLABEL ? du->dk_openpart : #endif - 0, - du->dk_dospartitions)) == 0) { + 0)) == 0) { int wlab; du->dk_flags |= DKFL_BSDLABEL; @@ -1474,8 +1465,7 @@ wdioctl(dev_t dev, int cmd, caddr_t addr, int flag) du->dk_openpart |= (1 << 0); /* XXX */ wlab = du->dk_wlabel; du->dk_wlabel = 1; - error = writedisklabel(dev, WDSTRATEGY, - &du->dk_dd, du->dk_dospartitions); + error = writedisklabel(dev, wdstrategy, &du->dk_dd); du->dk_openpart = du->dk_copenpart | du->dk_bopenpart; du->dk_wlabel = wlab; } @@ -1524,7 +1514,12 @@ wdformat(struct buf *bp) { bp->b_flags |= B_FORMAT; - return (wdstrategy(bp)); + wdstrategy(bp); + /* + * phk put this here, better that return(wdstrategy(bp)); + * XXX + */ + return -1; } #endif diff --git a/sys/isa/fd.c b/sys/isa/fd.c index a000acf89420..e06ac4aab450 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -40,7 +40,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.36 1994/10/21 16:58:50 joerg Exp $ + * $Id: fd.c,v 1.37 1994/10/23 21:27:12 wollman Exp $ * */ @@ -1522,7 +1522,7 @@ fdioctl(dev, cmd, addr, flag, p) dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; - if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL) + if (readdisklabel(dev, fdstrategy, dl, NULL, 0) == NULL) error = 0; else error = EINVAL; @@ -1550,11 +1550,11 @@ fdioctl(dev, cmd, addr, flag, p) dl = (struct disklabel *)addr; if ((error = - setdisklabel ((struct disklabel *)buffer, dl, 0, NULL))) + setdisklabel ((struct disklabel *)buffer, dl, 0))) break; error = writedisklabel(dev, fdstrategy, - (struct disklabel *)buffer, NULL); + (struct disklabel *)buffer); break; case FD_FORM: diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c index f1162693d9d0..484914632dc9 100644 --- a/sys/kern/subr_disklabel.c +++ b/sys/kern/subr_disklabel.c @@ -36,17 +36,17 @@ * SUCH DAMAGE. * * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 - * $Id: ufs_disksubr.c,v 1.4 1994/10/08 06:57:23 phk Exp $ + * $Id: ufs_disksubr.c,v 1.5 1994/10/17 02:31:33 phk Exp $ */ #include #include #include +#include #include #include #include -int dkcksum __P((struct disklabel *)); /* * Seek sort for disks. We depend on the driver which calls us using b_resid * as the current cylinder number. @@ -154,86 +154,53 @@ insert: bp->b_actf = bq->b_actf; * 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. + * If Machine Specific Partitions (MSP) are not found, then it will proceed + * as if the BSD partition starts at 0 + * The MBR on an IBM PC is an example of an MSP. */ char * readdisklabel(dev, strat, lp, dp, bdp) dev_t dev; - int (*strat)(); + void (*strat)(); register struct disklabel *lp; struct dos_partition *dp; struct dkbad *bdp; { register struct buf *bp; struct disklabel *dlp; + char *msgMSP = NULL; char *msg = NULL; - int dospartoff; int i; - int cyl; + int cyl = 0; + /* + * Set up the disklabel as in case there is no MSP. + * We set the BSD part, but don't need to set the + * RAW part, because readMSPtolabel() will reset that + * itself. On return however, if there was no MSP, + * then we will be looking into OUR part to find the label + * and we will want that to start at 0, and have at least SOME length. + */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; - lp->d_npartitions = 1; - if (lp->d_partitions[0].p_size == 0) - lp->d_partitions[0].p_size = 0x1fffffff; - lp->d_partitions[0].p_offset = 0; + lp->d_npartitions = OURPART + 1; + if (lp->d_partitions[OURPART].p_size == 0) + lp->d_partitions[OURPART].p_size = 0x100; /*enough for a label*/ + lp->d_partitions[OURPART].p_offset = 0; - bp = geteblk((int)lp->d_secsize); - /* do dos partitions in the process of getting disklabel? */ - dospartoff = 0; - cyl = LABELSECTOR / lp->d_secpercyl; - if (dp) { - /* read master boot record */ - bp->b_dev = dev; - 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 successful, wander through dos partition table */ - if (biowait(bp)) { - msg = "dos partition I/O error"; - goto done; - } else { - /* XXX how do we check veracity/bounds of this? */ - bcopy(bp->b_un.b_addr + DOSPARTOFF, dp, - NDOSPART * sizeof(*dp)); - for (i = 0; i < NDOSPART; i++, dp++) - /* is this ours? */ - if (dp->dp_size && - dp->dp_typ == DOSPTYP_386BSD - && dospartoff == 0) { - - /* need sector address for SCSI/IDE, - cylinder for ESDI/ST506/RLL */ - dospartoff = dp->dp_start; - cyl = DPCYL(dp->dp_scyl, dp->dp_ssect); - - /* update disklabel with details */ - lp->d_partitions[0].p_size = - dp->dp_size; - lp->d_partitions[0].p_offset = - dp->dp_start; - lp->d_ntracks = dp->dp_ehd + 1; - lp->d_nsectors = DPSECT(dp->dp_esect); -#ifdef CC_WALL -/* The next statement looks bogus... i runs int 0..3 ??? */ - lp->d_subtype |= ((lp->d_subtype & 3) - + i) | DSTYPE_INDOSPART; -#else /* CC_WALL */ - lp->d_subtype |= (lp->d_subtype & 3) - + i | DSTYPE_INDOSPART; -#endif /* CC_WALL */ - lp->d_secpercyl = lp->d_ntracks * - lp->d_nsectors; - } - } - - } + /* + * Dig out the Dos MSP.. If we get it, all remaining transfers + * will be relative to the base of the BSD part. + */ + msgMSP = readMSPtolabel(dev, strat, lp, dp, &cyl ); - /* next, dig out disk label */ - bp->b_blkno = dospartoff + LABELSECTOR; - bp->b_dev = dev; + /* + * next, dig out disk label, relative to either the base of the + * BSD part, or block 0, depending on if an MSP was found. + */ + bp = geteblk((int)lp->d_secsize); + bp->b_blkno = LABELSECTOR; + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART)); bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = cyl; @@ -256,8 +223,19 @@ readdisklabel(dev, strat, lp, dp, bdp) break; } } - if (msg) + + if (msg && msgMSP) { + msg = msgMSP; goto done; + } + + /* + * Since we had one of the two labels, either one made up from the + * MSP, one found in the FreeBSD-MSP-partitions sector 2, or even + * one in sector 2 absolute on the disk, there is not really an error. + */ + + msg = NULL; /* obtain bad sector table if requested and present */ if (bdp && (lp->d_flags & D_BADSECT)) { @@ -312,11 +290,20 @@ setdisklabel(olp, nlp, openmask) register i; register struct partition *opp, *npp; + /* + * Check it is actually a disklabel we are looking at. + */ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || dkcksum(nlp) != 0) return (EINVAL); + /* + * For each partition that we think is open, + */ while ((i = ffs((long)openmask)) != 0) { i--; + /* + * Check it is not changing.... + */ openmask &= ~(1 << i); if (nlp->d_npartitions <= i) return (EBUSY); @@ -327,6 +314,8 @@ setdisklabel(olp, nlp, openmask) /* * Copy internally-set partition information * if new label doesn't include it. XXX + * (If we are using it then we had better stay the same type) + * This is possibly dubious, as someone else noted (XXX) */ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { npp->p_fstype = opp->p_fstype; @@ -341,38 +330,100 @@ setdisklabel(olp, nlp, openmask) return (0); } -/* encoding of disk minor numbers, should be elsewhere... */ -#define dkunit(dev) (minor(dev) >> 3) -#define dkpart(dev) (minor(dev) & 07) -#define dkminor(unit, part) (((unit) << 3) | (part)) - /* * Write disk label back to device after modification. + * For FreeBSD 2.0(x86) this routine will refuse to install a label if + * there is no DOS MSP. (this can be changed) + * + * Assumptions for THIS VERSION: + * The given disklabel pointer is actually that which is controlling this + * Device, so that by fiddling it, readMSPtolabel() can ensure that + * it can read from the MSP if it exists, + * This assumption will cease as soon as ther is a better way of ensuring + * that a read is done to the whole raw device. + * MSP defines a BSD part, label is in block 1 (2nd block) of this */ int writedisklabel(dev, strat, lp) dev_t dev; - int (*strat)(); + void (*strat)(); register struct disklabel *lp; { - struct buf *bp; + struct buf *bp = NULL; struct disklabel *dlp; - int labelpart; int error = 0; + struct disklabel label; + char *msg; + int BSDstart,BSDlen; + int cyl; /* dummy arg for readMSPtolabel() */ - labelpart = dkpart(dev); - /* XXX this is wrong. But leaving it in is worse. */ -#ifndef __FREEBSD__ - if (lp->d_partitions[labelpart].p_offset != 0) { - if (lp->d_partitions[0].p_offset != 0) - return (EXDEV); /* not quite right */ - labelpart = 0; + /* + * Save the label (better be the real one) + * because we are going to play funny games with the disklabel + * controlling this device.. + */ + bcopy(lp,&label,sizeof(label)); + /* + * Unlike the read, we will trust the parameters given to us + * about the disk, in the new disklabel but will simply + * force OURPART to start at block 0 as a default in case there is NO + * MSP. + * readMSPtolabel() will reset it to start at the start of the BSD + * part if it exists + * At this time this is an error contition but I've left support for it + */ + lp->d_npartitions = OURPART + 1; + if (lp->d_partitions[OURPART].p_size == 0) + lp->d_partitions[OURPART].p_size = 0x1fffffff; + lp->d_partitions[OURPART].p_offset = 0; + + msg = readMSPtolabel(dev, strat, lp, 0, &cyl ); + /* + * If we want to be able to install without an Machine Specific + * Partitioning , then + * the failure of readMSPtolabel() should be made non fatal. + */ + if(msg) { + printf("writedisklabel:%s\n",msg); + error = ENXIO; + goto done; } -#endif + /* + * If we had MSP (no message) but there + * was no BSD part in it + * then balk.. they should use fdisk to make one first or smash it.. + * This may just be me being paranoid, but it's my choice for now.. + * note we test for !msg, because the test above might be changed + * as a valid option.. + */ + if((!msg) && (!(lp->d_subtype & DSTYPE_INDOSPART))) { + printf("writedisklabel: MSP with no BSD part\n"); + } + + /* + * get all the other bits back from the good new disklabel + * (the user wouldn't try confuse us would he?) + * With the exception of the OURPART which now points to the + * BSD partition. + */ + BSDstart = lp->d_partitions[OURPART].p_offset; + BSDlen = lp->d_partitions[OURPART].p_size; + bcopy(&label,lp,sizeof(label)); + lp->d_partitions[OURPART].p_offset = BSDstart; + lp->d_partitions[OURPART].p_size = BSDlen; + bp = geteblk((int)lp->d_secsize); - bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART)); bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; +#ifdef STUPID + /* + * We read the label first to see if it's there, + * in which case we will put ours at the same offset into the block.. + * (I think this is stupid [Julian]) + * Note that you can't write a label out over a corrupted label! + * (also stupid.. how do you write the first one? by raw writes?) + */ bp->b_flags = B_READ; (*strat)(bp); error = biowait(bp); @@ -384,7 +435,7 @@ writedisklabel(dev, strat, lp) dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && dkcksum(dlp) == 0) { - *dlp = *lp; + bcopy(&label,dlp,sizeof(label)); bp->b_flags = B_WRITE; (*strat)(bp); error = biowait(bp); @@ -392,15 +443,24 @@ writedisklabel(dev, strat, lp) } } error = ESRCH; +#else /* Stupid */ + dlp = (struct disklabel *)bp->b_data; + bcopy(&label,dlp,sizeof(label)); + bp->b_flags = B_WRITE; + (*strat)(bp); + error = biowait(bp); +#endif /* Stupid */ done: - brelse(bp); + bcopy(&label,lp,sizeof(label)); /* start using the new label again */ + if(bp) + brelse(bp); return (error); } /* * Compute checksum for disk label. */ -int +u_int dkcksum(lp) register struct disklabel *lp; { diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c index 9c94bb3dd29d..438d047d3e6a 100644 --- a/sys/scsi/cd.c +++ b/sys/scsi/cd.c @@ -14,7 +14,7 @@ * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * - * $Id: cd.c,v 1.26 1994/10/19 00:09:42 wollman Exp $ + * $Id: cd.c,v 1.27 1994/10/23 21:27:52 wollman Exp $ */ #define SPLCD splbio @@ -677,9 +677,7 @@ cdioctl(dev_t dev, int cmd, caddr_t addr, int flag) error = EBADF; else error = setdisklabel(&cd->disklabel, - (struct disklabel *) addr, - 0, - 0); + (struct disklabel *) addr, 0); if (error == 0) break; diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 6bfb807c9696..2223b97547a3 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -14,7 +14,7 @@ * * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 * - * $Id: sd.c,v 1.36 1994/10/20 00:08:31 phk Exp $ + * $Id: sd.c,v 1.37 1994/10/23 21:27:57 wollman Exp $ */ #define SPLSD splbio @@ -67,7 +67,6 @@ int Debugger(const char *); #define WHOLE_DISK(unit) ( (unit << UNITSHIFT) + RAW_PART ) -extern char *readdisklabel(); errval sdgetdisklabel __P((unsigned char unit)); errval sd_get_parms __P((int unit, int flags)); void sdstrategy __P((struct buf *)); @@ -782,6 +781,10 @@ sdgetdisklabel(unsigned char unit) /* * Call the generic disklabel extraction routine */ + sd->flags |= SDHAVELABEL; /* chicken and egg problem */ + /* we need to pretend this disklabel */ + /* is real before we can read */ + /* real disklabel */ errstring = readdisklabel(makedev(0, (unit << UNITSHIFT) + RAW_PART), sdstrategy, &sd->disklabel @@ -792,10 +795,10 @@ sdgetdisklabel(unsigned char unit) #endif ); if (errstring) { + sd->flags &= ~SDHAVELABEL; /* not now we don't */ printf("sd%d: %s\n", unit, errstring); return ENXIO; } - sd->flags |= SDHAVELABEL; /* WE HAVE IT ALL NOW */ return ESUCCESS; } diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index 38738cac9cb4..229d52b30bb9 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)disklabel.h 8.1 (Berkeley) 6/2/93 - * $Id: disklabel.h,v 1.4 1994/08/21 04:41:39 paul Exp $ + * $Id: disklabel.h,v 1.5 1994/10/20 23:41:57 paul Exp $ */ #ifndef _SYS_DISKLABEL_H_ @@ -54,6 +54,25 @@ #ifdef i386 #define LABELSECTOR 1 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ +#define OURPART 2 /* partition is 'all BSD' */ +#define RAWPART 3 /* partition is 'all device' */ +#define readMSPtolabel readMBRtolabel +#endif + +#ifndef readMSPtolabel +#define readMSPtolabel(a,b,c,d,e,) /* zap calls if irrelevant */ +#endif + +#ifdef tahoe +#define RAWPART 0 +#endif + +#ifndef RAWPART +#define RAWPART 2 +#endif + +#ifndef OURPART +#define OURPART RAWPART /* by default it's all ours */ #endif #ifndef LABELSECTOR @@ -358,6 +377,18 @@ extern struct dos_partition dos_partitions[NDOSPART]; #endif /* LOCORE */ +#ifdef KERNEL +u_int dkcksum __P((struct disklabel *)); +int writedisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp)); +char * readdisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp, struct dos_partition *dp, struct dkbad *bdp)); +int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp, u_long openmask)); +void disksort __P((struct buf *ap, struct buf *bp)); +void diskerr __P((struct buf *, char *, char *, int, int, struct disklabel *)); +#ifdef __i386 +char * readMBRtolabel __P(( dev_t dev , void (*strat)(), register struct disklabel *lp, struct dos_partition *dp, int *cyl)); +#endif +#endif + #if !defined(KERNEL) && !defined(LOCORE) #include @@ -368,4 +399,13 @@ __END_DECLS #endif +#ifdef __i386 +/* encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkpart(dev) (minor(dev) & 07) +#define dkminor(unit, part) (((unit) << 3) | (part)) #endif + +#endif + + diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index 38738cac9cb4..229d52b30bb9 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)disklabel.h 8.1 (Berkeley) 6/2/93 - * $Id: disklabel.h,v 1.4 1994/08/21 04:41:39 paul Exp $ + * $Id: disklabel.h,v 1.5 1994/10/20 23:41:57 paul Exp $ */ #ifndef _SYS_DISKLABEL_H_ @@ -54,6 +54,25 @@ #ifdef i386 #define LABELSECTOR 1 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ +#define OURPART 2 /* partition is 'all BSD' */ +#define RAWPART 3 /* partition is 'all device' */ +#define readMSPtolabel readMBRtolabel +#endif + +#ifndef readMSPtolabel +#define readMSPtolabel(a,b,c,d,e,) /* zap calls if irrelevant */ +#endif + +#ifdef tahoe +#define RAWPART 0 +#endif + +#ifndef RAWPART +#define RAWPART 2 +#endif + +#ifndef OURPART +#define OURPART RAWPART /* by default it's all ours */ #endif #ifndef LABELSECTOR @@ -358,6 +377,18 @@ extern struct dos_partition dos_partitions[NDOSPART]; #endif /* LOCORE */ +#ifdef KERNEL +u_int dkcksum __P((struct disklabel *)); +int writedisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp)); +char * readdisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp, struct dos_partition *dp, struct dkbad *bdp)); +int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp, u_long openmask)); +void disksort __P((struct buf *ap, struct buf *bp)); +void diskerr __P((struct buf *, char *, char *, int, int, struct disklabel *)); +#ifdef __i386 +char * readMBRtolabel __P(( dev_t dev , void (*strat)(), register struct disklabel *lp, struct dos_partition *dp, int *cyl)); +#endif +#endif + #if !defined(KERNEL) && !defined(LOCORE) #include @@ -368,4 +399,13 @@ __END_DECLS #endif +#ifdef __i386 +/* encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkpart(dev) (minor(dev) & 07) +#define dkminor(unit, part) (((unit) << 3) | (part)) #endif + +#endif + + diff --git a/sys/sys/diskpc98.h b/sys/sys/diskpc98.h index 38738cac9cb4..229d52b30bb9 100644 --- a/sys/sys/diskpc98.h +++ b/sys/sys/diskpc98.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)disklabel.h 8.1 (Berkeley) 6/2/93 - * $Id: disklabel.h,v 1.4 1994/08/21 04:41:39 paul Exp $ + * $Id: disklabel.h,v 1.5 1994/10/20 23:41:57 paul Exp $ */ #ifndef _SYS_DISKLABEL_H_ @@ -54,6 +54,25 @@ #ifdef i386 #define LABELSECTOR 1 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ +#define OURPART 2 /* partition is 'all BSD' */ +#define RAWPART 3 /* partition is 'all device' */ +#define readMSPtolabel readMBRtolabel +#endif + +#ifndef readMSPtolabel +#define readMSPtolabel(a,b,c,d,e,) /* zap calls if irrelevant */ +#endif + +#ifdef tahoe +#define RAWPART 0 +#endif + +#ifndef RAWPART +#define RAWPART 2 +#endif + +#ifndef OURPART +#define OURPART RAWPART /* by default it's all ours */ #endif #ifndef LABELSECTOR @@ -358,6 +377,18 @@ extern struct dos_partition dos_partitions[NDOSPART]; #endif /* LOCORE */ +#ifdef KERNEL +u_int dkcksum __P((struct disklabel *)); +int writedisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp)); +char * readdisklabel __P((dev_t dev, void (*strat)(), struct disklabel *lp, struct dos_partition *dp, struct dkbad *bdp)); +int setdisklabel __P((struct disklabel *olp, struct disklabel *nlp, u_long openmask)); +void disksort __P((struct buf *ap, struct buf *bp)); +void diskerr __P((struct buf *, char *, char *, int, int, struct disklabel *)); +#ifdef __i386 +char * readMBRtolabel __P(( dev_t dev , void (*strat)(), register struct disklabel *lp, struct dos_partition *dp, int *cyl)); +#endif +#endif + #if !defined(KERNEL) && !defined(LOCORE) #include @@ -368,4 +399,13 @@ __END_DECLS #endif +#ifdef __i386 +/* encoding of disk minor numbers, should be elsewhere... */ +#define dkunit(dev) (minor(dev) >> 3) +#define dkpart(dev) (minor(dev) & 07) +#define dkminor(unit, part) (((unit) << 3) | (part)) #endif + +#endif + + diff --git a/sys/ufs/ufs/ufs_disksubr.c b/sys/ufs/ufs/ufs_disksubr.c index f1162693d9d0..484914632dc9 100644 --- a/sys/ufs/ufs/ufs_disksubr.c +++ b/sys/ufs/ufs/ufs_disksubr.c @@ -36,17 +36,17 @@ * SUCH DAMAGE. * * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 - * $Id: ufs_disksubr.c,v 1.4 1994/10/08 06:57:23 phk Exp $ + * $Id: ufs_disksubr.c,v 1.5 1994/10/17 02:31:33 phk Exp $ */ #include #include #include +#include #include #include #include -int dkcksum __P((struct disklabel *)); /* * Seek sort for disks. We depend on the driver which calls us using b_resid * as the current cylinder number. @@ -154,86 +154,53 @@ insert: bp->b_actf = bq->b_actf; * 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. + * If Machine Specific Partitions (MSP) are not found, then it will proceed + * as if the BSD partition starts at 0 + * The MBR on an IBM PC is an example of an MSP. */ char * readdisklabel(dev, strat, lp, dp, bdp) dev_t dev; - int (*strat)(); + void (*strat)(); register struct disklabel *lp; struct dos_partition *dp; struct dkbad *bdp; { register struct buf *bp; struct disklabel *dlp; + char *msgMSP = NULL; char *msg = NULL; - int dospartoff; int i; - int cyl; + int cyl = 0; + /* + * Set up the disklabel as in case there is no MSP. + * We set the BSD part, but don't need to set the + * RAW part, because readMSPtolabel() will reset that + * itself. On return however, if there was no MSP, + * then we will be looking into OUR part to find the label + * and we will want that to start at 0, and have at least SOME length. + */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; - lp->d_npartitions = 1; - if (lp->d_partitions[0].p_size == 0) - lp->d_partitions[0].p_size = 0x1fffffff; - lp->d_partitions[0].p_offset = 0; + lp->d_npartitions = OURPART + 1; + if (lp->d_partitions[OURPART].p_size == 0) + lp->d_partitions[OURPART].p_size = 0x100; /*enough for a label*/ + lp->d_partitions[OURPART].p_offset = 0; - bp = geteblk((int)lp->d_secsize); - /* do dos partitions in the process of getting disklabel? */ - dospartoff = 0; - cyl = LABELSECTOR / lp->d_secpercyl; - if (dp) { - /* read master boot record */ - bp->b_dev = dev; - 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 successful, wander through dos partition table */ - if (biowait(bp)) { - msg = "dos partition I/O error"; - goto done; - } else { - /* XXX how do we check veracity/bounds of this? */ - bcopy(bp->b_un.b_addr + DOSPARTOFF, dp, - NDOSPART * sizeof(*dp)); - for (i = 0; i < NDOSPART; i++, dp++) - /* is this ours? */ - if (dp->dp_size && - dp->dp_typ == DOSPTYP_386BSD - && dospartoff == 0) { - - /* need sector address for SCSI/IDE, - cylinder for ESDI/ST506/RLL */ - dospartoff = dp->dp_start; - cyl = DPCYL(dp->dp_scyl, dp->dp_ssect); - - /* update disklabel with details */ - lp->d_partitions[0].p_size = - dp->dp_size; - lp->d_partitions[0].p_offset = - dp->dp_start; - lp->d_ntracks = dp->dp_ehd + 1; - lp->d_nsectors = DPSECT(dp->dp_esect); -#ifdef CC_WALL -/* The next statement looks bogus... i runs int 0..3 ??? */ - lp->d_subtype |= ((lp->d_subtype & 3) - + i) | DSTYPE_INDOSPART; -#else /* CC_WALL */ - lp->d_subtype |= (lp->d_subtype & 3) - + i | DSTYPE_INDOSPART; -#endif /* CC_WALL */ - lp->d_secpercyl = lp->d_ntracks * - lp->d_nsectors; - } - } - - } + /* + * Dig out the Dos MSP.. If we get it, all remaining transfers + * will be relative to the base of the BSD part. + */ + msgMSP = readMSPtolabel(dev, strat, lp, dp, &cyl ); - /* next, dig out disk label */ - bp->b_blkno = dospartoff + LABELSECTOR; - bp->b_dev = dev; + /* + * next, dig out disk label, relative to either the base of the + * BSD part, or block 0, depending on if an MSP was found. + */ + bp = geteblk((int)lp->d_secsize); + bp->b_blkno = LABELSECTOR; + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART)); bp->b_bcount = lp->d_secsize; bp->b_flags = B_BUSY | B_READ; bp->b_cylinder = cyl; @@ -256,8 +223,19 @@ readdisklabel(dev, strat, lp, dp, bdp) break; } } - if (msg) + + if (msg && msgMSP) { + msg = msgMSP; goto done; + } + + /* + * Since we had one of the two labels, either one made up from the + * MSP, one found in the FreeBSD-MSP-partitions sector 2, or even + * one in sector 2 absolute on the disk, there is not really an error. + */ + + msg = NULL; /* obtain bad sector table if requested and present */ if (bdp && (lp->d_flags & D_BADSECT)) { @@ -312,11 +290,20 @@ setdisklabel(olp, nlp, openmask) register i; register struct partition *opp, *npp; + /* + * Check it is actually a disklabel we are looking at. + */ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || dkcksum(nlp) != 0) return (EINVAL); + /* + * For each partition that we think is open, + */ while ((i = ffs((long)openmask)) != 0) { i--; + /* + * Check it is not changing.... + */ openmask &= ~(1 << i); if (nlp->d_npartitions <= i) return (EBUSY); @@ -327,6 +314,8 @@ setdisklabel(olp, nlp, openmask) /* * Copy internally-set partition information * if new label doesn't include it. XXX + * (If we are using it then we had better stay the same type) + * This is possibly dubious, as someone else noted (XXX) */ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { npp->p_fstype = opp->p_fstype; @@ -341,38 +330,100 @@ setdisklabel(olp, nlp, openmask) return (0); } -/* encoding of disk minor numbers, should be elsewhere... */ -#define dkunit(dev) (minor(dev) >> 3) -#define dkpart(dev) (minor(dev) & 07) -#define dkminor(unit, part) (((unit) << 3) | (part)) - /* * Write disk label back to device after modification. + * For FreeBSD 2.0(x86) this routine will refuse to install a label if + * there is no DOS MSP. (this can be changed) + * + * Assumptions for THIS VERSION: + * The given disklabel pointer is actually that which is controlling this + * Device, so that by fiddling it, readMSPtolabel() can ensure that + * it can read from the MSP if it exists, + * This assumption will cease as soon as ther is a better way of ensuring + * that a read is done to the whole raw device. + * MSP defines a BSD part, label is in block 1 (2nd block) of this */ int writedisklabel(dev, strat, lp) dev_t dev; - int (*strat)(); + void (*strat)(); register struct disklabel *lp; { - struct buf *bp; + struct buf *bp = NULL; struct disklabel *dlp; - int labelpart; int error = 0; + struct disklabel label; + char *msg; + int BSDstart,BSDlen; + int cyl; /* dummy arg for readMSPtolabel() */ - labelpart = dkpart(dev); - /* XXX this is wrong. But leaving it in is worse. */ -#ifndef __FREEBSD__ - if (lp->d_partitions[labelpart].p_offset != 0) { - if (lp->d_partitions[0].p_offset != 0) - return (EXDEV); /* not quite right */ - labelpart = 0; + /* + * Save the label (better be the real one) + * because we are going to play funny games with the disklabel + * controlling this device.. + */ + bcopy(lp,&label,sizeof(label)); + /* + * Unlike the read, we will trust the parameters given to us + * about the disk, in the new disklabel but will simply + * force OURPART to start at block 0 as a default in case there is NO + * MSP. + * readMSPtolabel() will reset it to start at the start of the BSD + * part if it exists + * At this time this is an error contition but I've left support for it + */ + lp->d_npartitions = OURPART + 1; + if (lp->d_partitions[OURPART].p_size == 0) + lp->d_partitions[OURPART].p_size = 0x1fffffff; + lp->d_partitions[OURPART].p_offset = 0; + + msg = readMSPtolabel(dev, strat, lp, 0, &cyl ); + /* + * If we want to be able to install without an Machine Specific + * Partitioning , then + * the failure of readMSPtolabel() should be made non fatal. + */ + if(msg) { + printf("writedisklabel:%s\n",msg); + error = ENXIO; + goto done; } -#endif + /* + * If we had MSP (no message) but there + * was no BSD part in it + * then balk.. they should use fdisk to make one first or smash it.. + * This may just be me being paranoid, but it's my choice for now.. + * note we test for !msg, because the test above might be changed + * as a valid option.. + */ + if((!msg) && (!(lp->d_subtype & DSTYPE_INDOSPART))) { + printf("writedisklabel: MSP with no BSD part\n"); + } + + /* + * get all the other bits back from the good new disklabel + * (the user wouldn't try confuse us would he?) + * With the exception of the OURPART which now points to the + * BSD partition. + */ + BSDstart = lp->d_partitions[OURPART].p_offset; + BSDlen = lp->d_partitions[OURPART].p_size; + bcopy(&label,lp,sizeof(label)); + lp->d_partitions[OURPART].p_offset = BSDstart; + lp->d_partitions[OURPART].p_size = BSDlen; + bp = geteblk((int)lp->d_secsize); - bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); + bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), OURPART)); bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; +#ifdef STUPID + /* + * We read the label first to see if it's there, + * in which case we will put ours at the same offset into the block.. + * (I think this is stupid [Julian]) + * Note that you can't write a label out over a corrupted label! + * (also stupid.. how do you write the first one? by raw writes?) + */ bp->b_flags = B_READ; (*strat)(bp); error = biowait(bp); @@ -384,7 +435,7 @@ writedisklabel(dev, strat, lp) dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && dkcksum(dlp) == 0) { - *dlp = *lp; + bcopy(&label,dlp,sizeof(label)); bp->b_flags = B_WRITE; (*strat)(bp); error = biowait(bp); @@ -392,15 +443,24 @@ writedisklabel(dev, strat, lp) } } error = ESRCH; +#else /* Stupid */ + dlp = (struct disklabel *)bp->b_data; + bcopy(&label,dlp,sizeof(label)); + bp->b_flags = B_WRITE; + (*strat)(bp); + error = biowait(bp); +#endif /* Stupid */ done: - brelse(bp); + bcopy(&label,lp,sizeof(label)); /* start using the new label again */ + if(bp) + brelse(bp); return (error); } /* * Compute checksum for disk label. */ -int +u_int dkcksum(lp) register struct disklabel *lp; { diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index 8370ecf10e9d..7e621401ae19 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ufs_extern.h 8.3 (Berkeley) 4/16/94 - * $Id: ufs_extern.h,v 1.3 1994/08/21 07:16:17 paul Exp $ + * $Id: ufs_extern.h,v 1.4 1994/09/22 19:38:40 wollman Exp $ */ #ifndef _UFS_UFS_UFS_EXTERN_H_ @@ -54,14 +54,6 @@ struct vnode; struct ufs_args; __BEGIN_DECLS -void diskerr - __P((struct buf *, char *, char *, int, int, struct disklabel *)); -void disksort __P((struct buf *, struct buf *)); -u_int dkcksum __P((struct disklabel *)); -char *readdisklabel __P((dev_t, int (*)(), struct disklabel *)); -int setdisklabel __P((struct disklabel *, struct disklabel *, u_long)); -int writedisklabel __P((dev_t, int (*)(), struct disklabel *)); - int ufs_abortop __P((struct vop_abortop_args *)); int ufs_access __P((struct vop_access_args *)); int ufs_advlock __P((struct vop_advlock_args *));