diff options
Diffstat (limited to 'sys/i386/isa/readMBR.c')
-rw-r--r-- | sys/i386/isa/readMBR.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/sys/i386/isa/readMBR.c b/sys/i386/isa/readMBR.c new file mode 100644 index 0000000..4165d21 --- /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 <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/disklabel.h> + +#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; i<MAXPARTITIONS; i++) { + lp->d_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; +} + + |