238 lines
6.8 KiB
C
238 lines
6.8 KiB
C
/*
|
|
*
|
|
* 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.2 1994/10/28 12:41:55 jkh Exp $
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/dkbad.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)) {
|
|
printf("disk doesn't have an MBR\n");
|
|
if(dp)
|
|
bzero(bp->b_un.b_addr + DOSPARTOFF,
|
|
NDOSPART * sizeof(*dp));
|
|
goto hrumpf;
|
|
}
|
|
|
|
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;
|
|
}
|
|
hrumpf:
|
|
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;
|
|
}
|
|
|
|
|