From 0300a965c81005f9ddae5dc486603a8db81385c3 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Mon, 12 Dec 1994 00:22:30 +0000 Subject: [PATCH] diskslice_machdep.c implements reading and checking of DOS slice tables. It will eventually replace readMBR.c. --- sys/i386/isa/diskslice_machdep.c | 212 +++++++++++++++++++++++++++++++ sys/kern/subr_diskmbr.c | 212 +++++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+) create mode 100644 sys/i386/isa/diskslice_machdep.c create mode 100644 sys/kern/subr_diskmbr.c diff --git a/sys/i386/isa/diskslice_machdep.c b/sys/i386/isa/diskslice_machdep.c new file mode 100644 index 000000000000..d640ed902b26 --- /dev/null +++ b/sys/i386/isa/diskslice_machdep.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 1994 Bruce D. Evans. + * All rights reserved. + * + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ + * $Id: + */ + +#include +#include +#include +#include +#include +#include +#include + +int +dsinit(dname, dev, strat, lp, sspp) + char *dname; + dev_t dev; + d_strategy_t *strat; + struct disklabel *lp; + struct diskslices **sspp; +{ + struct buf *bp; + u_char *cp; + struct dos_partition *dp; + struct dos_partition *dp0; + int error; + int max_nsectors; + int max_ntracks; + u_long secpercyl; + int slice; + struct diskslice *sp; + struct diskslices *ssp; + + /* + * Free old slices "struct", if any, and allocate a dummy new one. + */ + if (*sspp != NULL) + free(*sspp, M_DEVBUF); + ssp = malloc(offsetof(struct diskslices, dss_slices) + sizeof(*sp), + M_DEVBUF, M_WAITOK); + *sspp = ssp; + + /* + * Initialize dummy slice. If there is an error, this becomes the + * only slice, and no more restrictive than the (dummy) label. + */ + sp = &ssp->dss_slices[0]; + bzero(sp, sizeof *sp); + sp->ds_size = lp->d_secperunit; + ssp->dss_nslices = 1; + + /* Read master boot record. */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); + bp->b_blkno = DOSBBSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp) != 0) { + error = EIO; + goto done; + } + + /* Weakly verify it. */ + cp = bp->b_un.b_addr; + if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) { + error = EINVAL; + goto done; + } + + /* Guess the geometry. */ + /* + * TODO: + * Perhaps skip entries with 0 size. + * Perhaps only look at entries of type DOSPTYP_386BSD. + */ + max_nsectors = 0; + max_ntracks = 0; + dp0 = (struct dos_partition *)(cp + DOSPARTOFF); + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++) { + int nsectors; + int ntracks; + + nsectors = DPSECT(dp->dp_esect); + if (max_nsectors < nsectors) + max_nsectors = nsectors; + ntracks = dp->dp_ehd + 1; + if (max_ntracks < ntracks) + max_ntracks = ntracks; + } + + /* Check the geometry. */ + /* + * TODO: + * As above. + * Check for overlaps. + * Check or adjust against d_ncylinders and d_secperunit. + */ + error = 0; + secpercyl = max_nsectors * max_ntracks; + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++) { + u_long esector; + u_long esector1; + u_long ssector; + + if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0 + && dp->dp_start == 0 && dp->dp_size == 0) + continue; + ssector = DPSECT(dp->dp_ssect) - 1 + dp->dp_shd * max_nsectors + + DPCYL(dp->dp_scyl, dp->dp_ssect) * secpercyl; + esector = DPSECT(dp->dp_esect) - 1 + dp->dp_ehd * max_nsectors + + DPCYL(dp->dp_ecyl, dp->dp_esect) * secpercyl; + esector1 = dp->dp_start + dp->dp_size - 1; + if (ssector != dp->dp_start || esector != esector1) + error = EINVAL; +#if 1 + else + printf("%s%ds%d: start %lu, end = %lu, size %lu: OK\n", + dname, dkunit(dev), slice, ssector, esector, + dp->dp_size); + if (ssector != dp->dp_start) + printf( + "%s%ds%d: C/H/S start %lu != start %lu: invalid\n", + dname, dkunit(dev), slice, ssector, + dp->dp_start); + if (esector != esector1) + printf( + "%s%ds%d: C/H/S end %lu != end %lu: invalid\n", + dname, dkunit(dev), slice, esector, esector1); +#endif + } + if (error != 0) + goto done; + + /* + * We're not handling extended partitions yet, so there are always + * 1 + NDOSPART slices. + */ + if (dkslice(dev) >= 1 + NDOSPART) { + error = ENXIO; + goto done; + } + + /* + * Accept the DOS partition table. + * Free dummy slices "struct" and allocate a real new one. + */ + free(ssp, M_DEVBUF); + ssp = malloc(offsetof(struct diskslices, dss_slices) + + (1 + NDOSPART) * sizeof(*sp), M_DEVBUF, M_WAITOK); + *sspp = ssp; + sp = &ssp->dss_slices[0]; + bzero(sp, (1 + NDOSPART) * sizeof *sp); + sp->ds_size = lp->d_secperunit; + sp++; + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++, sp++) { + sp->ds_offset = dp->dp_start; + sp->ds_size = dp->dp_size; + } + ssp->dss_nslices = 1 + NDOSPART; + if (max_nsectors != 0) { + lp->d_nsectors = max_nsectors; + lp->d_ntracks = max_ntracks; + lp->d_secpercyl = secpercyl; + } +#if 0 + lp->d_secperunit = what?; + lp->d_subtype |= (lp->d_subtype & 3) + (slice - 1) | DSTYPE_INDOSPART; +#endif + +done: + bp->b_flags = B_INVAL | B_AGE; + brelse(bp); + if (error == EINVAL) + error = (dkslice(dev) == 0 ? 0 : ENXIO); + return (error); +} diff --git a/sys/kern/subr_diskmbr.c b/sys/kern/subr_diskmbr.c new file mode 100644 index 000000000000..d640ed902b26 --- /dev/null +++ b/sys/kern/subr_diskmbr.c @@ -0,0 +1,212 @@ +/*- + * Copyright (c) 1994 Bruce D. Evans. + * All rights reserved. + * + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ + * $Id: + */ + +#include +#include +#include +#include +#include +#include +#include + +int +dsinit(dname, dev, strat, lp, sspp) + char *dname; + dev_t dev; + d_strategy_t *strat; + struct disklabel *lp; + struct diskslices **sspp; +{ + struct buf *bp; + u_char *cp; + struct dos_partition *dp; + struct dos_partition *dp0; + int error; + int max_nsectors; + int max_ntracks; + u_long secpercyl; + int slice; + struct diskslice *sp; + struct diskslices *ssp; + + /* + * Free old slices "struct", if any, and allocate a dummy new one. + */ + if (*sspp != NULL) + free(*sspp, M_DEVBUF); + ssp = malloc(offsetof(struct diskslices, dss_slices) + sizeof(*sp), + M_DEVBUF, M_WAITOK); + *sspp = ssp; + + /* + * Initialize dummy slice. If there is an error, this becomes the + * only slice, and no more restrictive than the (dummy) label. + */ + sp = &ssp->dss_slices[0]; + bzero(sp, sizeof *sp); + sp->ds_size = lp->d_secperunit; + ssp->dss_nslices = 1; + + /* Read master boot record. */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); + bp->b_blkno = DOSBBSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp) != 0) { + error = EIO; + goto done; + } + + /* Weakly verify it. */ + cp = bp->b_un.b_addr; + if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) { + error = EINVAL; + goto done; + } + + /* Guess the geometry. */ + /* + * TODO: + * Perhaps skip entries with 0 size. + * Perhaps only look at entries of type DOSPTYP_386BSD. + */ + max_nsectors = 0; + max_ntracks = 0; + dp0 = (struct dos_partition *)(cp + DOSPARTOFF); + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++) { + int nsectors; + int ntracks; + + nsectors = DPSECT(dp->dp_esect); + if (max_nsectors < nsectors) + max_nsectors = nsectors; + ntracks = dp->dp_ehd + 1; + if (max_ntracks < ntracks) + max_ntracks = ntracks; + } + + /* Check the geometry. */ + /* + * TODO: + * As above. + * Check for overlaps. + * Check or adjust against d_ncylinders and d_secperunit. + */ + error = 0; + secpercyl = max_nsectors * max_ntracks; + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++) { + u_long esector; + u_long esector1; + u_long ssector; + + if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0 + && dp->dp_start == 0 && dp->dp_size == 0) + continue; + ssector = DPSECT(dp->dp_ssect) - 1 + dp->dp_shd * max_nsectors + + DPCYL(dp->dp_scyl, dp->dp_ssect) * secpercyl; + esector = DPSECT(dp->dp_esect) - 1 + dp->dp_ehd * max_nsectors + + DPCYL(dp->dp_ecyl, dp->dp_esect) * secpercyl; + esector1 = dp->dp_start + dp->dp_size - 1; + if (ssector != dp->dp_start || esector != esector1) + error = EINVAL; +#if 1 + else + printf("%s%ds%d: start %lu, end = %lu, size %lu: OK\n", + dname, dkunit(dev), slice, ssector, esector, + dp->dp_size); + if (ssector != dp->dp_start) + printf( + "%s%ds%d: C/H/S start %lu != start %lu: invalid\n", + dname, dkunit(dev), slice, ssector, + dp->dp_start); + if (esector != esector1) + printf( + "%s%ds%d: C/H/S end %lu != end %lu: invalid\n", + dname, dkunit(dev), slice, esector, esector1); +#endif + } + if (error != 0) + goto done; + + /* + * We're not handling extended partitions yet, so there are always + * 1 + NDOSPART slices. + */ + if (dkslice(dev) >= 1 + NDOSPART) { + error = ENXIO; + goto done; + } + + /* + * Accept the DOS partition table. + * Free dummy slices "struct" and allocate a real new one. + */ + free(ssp, M_DEVBUF); + ssp = malloc(offsetof(struct diskslices, dss_slices) + + (1 + NDOSPART) * sizeof(*sp), M_DEVBUF, M_WAITOK); + *sspp = ssp; + sp = &ssp->dss_slices[0]; + bzero(sp, (1 + NDOSPART) * sizeof *sp); + sp->ds_size = lp->d_secperunit; + sp++; + for (dp = dp0, slice = 1; slice <= NDOSPART; dp++, slice++, sp++) { + sp->ds_offset = dp->dp_start; + sp->ds_size = dp->dp_size; + } + ssp->dss_nslices = 1 + NDOSPART; + if (max_nsectors != 0) { + lp->d_nsectors = max_nsectors; + lp->d_ntracks = max_ntracks; + lp->d_secpercyl = secpercyl; + } +#if 0 + lp->d_secperunit = what?; + lp->d_subtype |= (lp->d_subtype & 3) + (slice - 1) | DSTYPE_INDOSPART; +#endif + +done: + bp->b_flags = B_INVAL | B_AGE; + brelse(bp); + if (error == EINVAL) + error = (dkslice(dev) == 0 ? 0 : ENXIO); + return (error); +}