summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/readMBR.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/isa/readMBR.c')
-rw-r--r--sys/i386/isa/readMBR.c232
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;
+}
+
+
OpenPOWER on IntegriCloud