NO_GEOM cleanup: retire to attic.

This commit is contained in:
Poul-Henning Kamp 2003-01-30 12:58:55 +00:00
parent c9834aa961
commit c5cab5b2fa
4 changed files with 0 additions and 2174 deletions

View File

@ -1,301 +0,0 @@
#ifdef NO_GEOM
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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.
*
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/stdint.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/syslog.h>
dev_t
dkmodpart(dev_t dev, int part)
{
return (makedev(major(dev), (minor(dev) & ~7) | part));
}
/*
* Attempt to read a disk label from a device using the indicated strategy
* routine. The label must be partly set up before this: secpercyl, secsize
* and anything required in the strategy routine (e.g., dummy bounds for the
* partition containing the label) must be filled in before calling us.
* Returns NULL on success and an error string on failure.
*/
char *
readdisklabel(dev, lp)
dev_t dev;
register struct disklabel *lp;
{
register struct buf *bp;
struct disklabel *dlp;
char *msg = NULL;
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
bp->b_bcount = lp->d_secsize;
bp->b_flags &= ~B_INVAL;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp);
if (bufwait(bp))
msg = "I/O error";
else if (bp->b_resid != 0)
msg = "disk too small for a label";
else for (dlp = (struct disklabel *)bp->b_data;
dlp <= (struct disklabel *)((char *)bp->b_data +
lp->d_secsize - sizeof(*dlp));
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
if (msg == NULL)
msg = "no disk label";
} else if (dlp->d_npartitions > MAXPARTITIONS ||
dkcksum(dlp) != 0)
msg = "disk label corrupted";
else {
*lp = *dlp;
msg = NULL;
break;
}
}
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
return (msg);
}
/*
* Check new disk label for sensibility before setting it.
*/
int
setdisklabel(olp, nlp, openmask)
register struct disklabel *olp, *nlp;
u_long openmask;
{
register int 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);
opp = &olp->d_partitions[i];
npp = &nlp->d_partitions[i];
if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
return (EBUSY);
/*
* 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;
npp->p_fsize = opp->p_fsize;
npp->p_frag = opp->p_frag;
npp->p_cpg = opp->p_cpg;
}
}
nlp->d_checksum = 0;
nlp->d_checksum = dkcksum(nlp);
*olp = *nlp;
return (0);
}
/*
* Write disk label back to device after modification.
*/
int
writedisklabel(dev, lp)
dev_t dev;
register struct disklabel *lp;
{
struct buf *bp;
struct disklabel *dlp;
int error = 0;
if (lp->d_partitions[RAW_PART].p_offset != 0)
return (EXDEV); /* not quite right */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dkmodpart(dev, RAW_PART);
bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
bp->b_bcount = lp->d_secsize;
#if 1
/*
* 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_INVAL;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp);
error = bufwait(bp);
if (error)
goto done;
if (bp->b_resid != 0) {
error = ENOSPC;
goto done;
}
for (dlp = (struct disklabel *)bp->b_data;
dlp <= (struct disklabel *)
((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
dkcksum(dlp) == 0) {
*dlp = *lp;
bp->b_flags &= ~B_DONE;
bp->b_iocmd = BIO_WRITE;
#ifdef __alpha__
alpha_fix_srm_checksum(bp);
#endif
DEV_STRATEGY(bp);
error = bufwait(bp);
goto done;
}
}
error = ESRCH;
done:
#else
bzero(bp->b_data, lp->d_secsize);
dlp = (struct disklabel *)bp->b_data;
*dlp = *lp;
bp->b_flags &= ~B_INVAL;
bp->b_iocmd = BIO_WRITE;
DEV_STRATEGY(bp);
error = bufwait(bp);
#endif
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
return (error);
}
/*
* Determine the size of the transfer, and make sure it is
* within the boundaries of the partition. Adjust transfer
* if needed, and signal errors or early completion.
*/
int
bounds_check_with_label(struct bio *bp, struct disklabel *lp, int wlabel)
{
struct partition *p = lp->d_partitions + dkpart(bp->bio_dev);
int labelsect = lp->d_partitions[0].p_offset;
int maxsz = p->p_size,
sz = (bp->bio_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
/* overwriting disk label ? */
/* XXX should also protect bootstrap in first 8K */
if (bp->bio_blkno + p->p_offset <= LABELSECTOR + labelsect &&
#if LABELSECTOR != 0
bp->bio_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
#endif
(bp->bio_cmd == BIO_WRITE) && wlabel == 0) {
bp->bio_error = EROFS;
goto bad;
}
#if defined(DOSBBSECTOR) && defined(notyet)
/* overwriting master boot record? */
if (bp->bio_blkno + p->p_offset <= DOSBBSECTOR &&
(bp->bio_cmd == BIO_WRITE) && wlabel == 0) {
bp->bio_error = EROFS;
goto bad;
}
#endif
/* beyond partition? */
if (bp->bio_blkno < 0 || bp->bio_blkno + sz > maxsz) {
/* if exactly at end of disk, return an EOF */
if (bp->bio_blkno == maxsz) {
bp->bio_resid = bp->bio_bcount;
return(0);
}
/* or truncate if part of it fits */
sz = maxsz - bp->bio_blkno;
if (sz <= 0) {
bp->bio_error = EINVAL;
goto bad;
}
bp->bio_bcount = sz << DEV_BSHIFT;
}
bp->bio_pblkno = bp->bio_blkno + p->p_offset;
return(1);
bad:
bp->bio_flags |= BIO_ERROR;
return(-1);
}
#ifdef __alpha__
void
alpha_fix_srm_checksum(bp)
struct buf *bp;
{
u_int64_t *p;
u_int64_t sum;
int i;
p = (u_int64_t *) bp->b_data;
sum = 0;
for (i = 0; i < 63; i++)
sum += p[i];
p[63] = sum;
}
#endif
#endif

View File

@ -1,529 +0,0 @@
#ifdef NO_GEOM
/*-
* 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 $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
#ifdef PC98
#define PC98_ATCOMPAT
#define dsinit atcompat_dsinit
#endif
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/diskmbr.h>
#define DOSPTYP_EXTENDED 5
#define DOSPTYP_EXTENDEDX 15
#define DOSPTYP_ONTRACK 84
#include <sys/diskslice.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#define TRACE(str) do { if (dsi_debug) printf str; } while (0)
static volatile u_char dsi_debug;
/*
* This is what we have embedded in every boot1 for supporting the bogus
* "Dangerously Dedicated" mode. However, the old table is broken because
* it has an illegal geometry in it - it specifies 256 heads (heads = end
* head + 1) which causes nasty stuff when that wraps to zero in bios code.
* eg: divide by zero etc. This caused the dead-thinkpad problem, numerous
* SCSI bios crashes, EFI to crash, etc.
*
* We still have to recognize the old table though, even though we stopped
* inflicting it apon the world.
*/
static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
};
static struct dos_partition historical_bogus_partition_table_fixed[NDOSPART] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 0x80, 0, 1, 0, DOSPTYP_386BSD, 254, 255, 255, 0, 50000, },
};
static int check_part(char *sname, struct dos_partition *dp,
u_long offset, int nsectors, int ntracks,
u_long mbr_offset);
static void mbr_extended(dev_t dev, struct disklabel *lp,
struct diskslices *ssp, u_long ext_offset,
u_long ext_size, u_long base_ext_offset,
int nsectors, int ntracks, u_long mbr_offset,
int level);
static int mbr_setslice(char *sname, struct disklabel *lp,
struct diskslice *sp, struct dos_partition *dp,
u_long br_offset);
static int
check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
char *sname;
struct dos_partition *dp;
u_long offset;
int nsectors;
int ntracks;
u_long mbr_offset;
{
int chs_ecyl;
int chs_esect;
int chs_scyl;
int chs_ssect;
int error;
u_long esector;
u_long esector1;
u_long secpercyl;
u_long ssector;
u_long ssector1;
secpercyl = (u_long)nsectors * ntracks;
chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
chs_ssect = DPSECT(dp->dp_ssect);
ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl
+ mbr_offset;
ssector1 = offset + dp->dp_start;
/*
* If ssector1 is on a cylinder >= 1024, then ssector can't be right.
* Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
* apart from the cylinder being reduced modulo 1024. Always allow
* 1023/255/63, because this is the official way to represent
* pure-LBA for the starting position.
*/
if ((ssector < ssector1
&& ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
&& chs_scyl == 1023)
|| (secpercyl != 0
&& (ssector1 - ssector) % (1024 * secpercyl) == 0)))
|| (dp->dp_scyl == 255 && dp->dp_shd == 255
&& dp->dp_ssect == 255)) {
TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
ssector = ssector1;
}
chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect);
chs_esect = DPSECT(dp->dp_esect);
esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl
+ mbr_offset;
esector1 = ssector1 + dp->dp_size - 1;
/*
* Allow certain bogus C/H/S values for esector, as above. However,
* heads == 255 isn't really legal and causes some BIOS crashes. The
* correct value to indicate a pure-LBA end is 1023/heads-1/sectors -
* usually 1023/254/63. "heads" is base 0, "sectors" is base 1.
*/
if ((esector < esector1
&& ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
&& chs_ecyl == 1023)
|| (secpercyl != 0
&& (esector1 - esector) % (1024 * secpercyl) == 0)))
|| (dp->dp_ecyl == 255 && dp->dp_ehd == 255
&& dp->dp_esect == 255)) {
TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
esector = esector1;
}
error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
if (bootverbose)
printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n",
sname, dp->dp_typ, ssector1, esector1,
(u_long)dp->dp_size, error ? "" : ": OK");
if (ssector != ssector1 && bootverbose)
printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
sname, chs_scyl, dp->dp_shd, chs_ssect,
ssector, ssector1);
if (esector != esector1 && bootverbose)
printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect,
esector, esector1);
return (error);
}
int
dsinit(dev, lp, sspp)
dev_t dev;
struct disklabel *lp;
struct diskslices **sspp;
{
struct buf *bp;
u_char *cp;
int dospart;
struct dos_partition *dp;
struct dos_partition *dp0;
struct dos_partition dpcopy[NDOSPART];
int error;
int max_ncyls;
int max_nsectors;
int max_ntracks;
u_long mbr_offset;
char partname[2];
u_long secpercyl;
char *sname;
struct diskslice *sp;
struct diskslices *ssp;
mbr_offset = DOSBBSECTOR;
reread_mbr:
/* Read master boot record. */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
bp->b_blkno = mbr_offset;
bp->b_bcount = lp->d_secsize;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp);
if (bufwait(bp) != 0) {
disk_err(&bp->b_io, "reading primary partition table: error",
0, 1);
error = EIO;
goto done;
}
/* Weakly verify it. */
cp = bp->b_data;
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
if (bootverbose)
printf("%s: invalid primary partition table: no magic\n",
sname);
error = EINVAL;
goto done;
}
/* Make a copy of the partition table to avoid alignment problems. */
memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
dp0 = &dpcopy[0];
/* Check for "Ontrack Diskmanager". */
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
if (dp->dp_typ == DOSPTYP_ONTRACK) {
if (bootverbose)
printf(
"%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
mbr_offset = 63;
goto reread_mbr;
}
}
if (bcmp(dp0, historical_bogus_partition_table,
sizeof historical_bogus_partition_table) == 0 ||
bcmp(dp0, historical_bogus_partition_table_fixed,
sizeof historical_bogus_partition_table_fixed) == 0) {
if (bootverbose)
printf(
"%s: invalid primary partition table: Dangerously Dedicated (ignored)\n",
sname);
error = EINVAL;
goto done;
}
/* Guess the geometry. */
/*
* TODO:
* Perhaps skip entries with 0 size.
* Perhaps only look at entries of type DOSPTYP_386BSD.
*/
max_ncyls = 0;
max_nsectors = 0;
max_ntracks = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
int ncyls;
int nsectors;
int ntracks;
ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
if (max_ncyls < ncyls)
max_ncyls = ncyls;
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 that we have guessed the geometry right by checking the
* partition entries.
*/
/*
* TODO:
* As above.
* Check for overlaps.
* Check against d_secperunit if the latter is reliable.
*/
error = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
&& dp->dp_start == 0 && dp->dp_size == 0)
continue;
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
/*
* Temporarily ignore errors from this check. We could
* simplify things by accepting the table eariler if we
* always ignore errors here. Perhaps we should always
* accept the table if the magic is right but not let
* bad entries affect the geometry.
*/
check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
mbr_offset);
}
if (error != 0)
goto done;
/*
* Accept the DOS partition table.
* First adjust the label (we have been careful not to change it
* before we can guarantee success).
*/
secpercyl = (u_long)max_nsectors * max_ntracks;
if (secpercyl != 0) {
lp->d_nsectors = max_nsectors;
lp->d_ntracks = max_ntracks;
lp->d_secpercyl = secpercyl;
lp->d_ncylinders = lp->d_secperunit / secpercyl;
}
/*
* We are passed a pointer to a suitably initialized minimal
* slices "struct" with no dangling pointers in it. Replace it
* by a maximal one. This usually oversizes the "struct", but
* enlarging it while searching for logical drives would be
* inconvenient.
*/
free(*sspp, M_DEVBUF);
ssp = dsmakeslicestruct(MAX_SLICES, lp);
*sspp = ssp;
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
(void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
}
ssp->dss_nslices = BASE_SLICE + NDOSPART;
/* Handle extended partitions. */
sp -= NDOSPART;
for (dospart = 0; dospart < NDOSPART; dospart++, sp++)
if (sp->ds_type == DOSPTYP_EXTENDED ||
sp->ds_type == DOSPTYP_EXTENDEDX)
mbr_extended(bp->b_dev, lp, ssp,
sp->ds_offset, sp->ds_size, sp->ds_offset,
max_nsectors, max_ntracks, mbr_offset, 1);
/*
* mbr_extended() abuses ssp->dss_nslices for the number of slices
* that would be found if there were no limit on the number of slices
* in *ssp. Cut it back now.
*/
if (ssp->dss_nslices > MAX_SLICES)
ssp->dss_nslices = MAX_SLICES;
done:
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
if (error == EINVAL)
error = 0;
return (error);
}
static void
mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
ntracks, mbr_offset, level)
dev_t dev;
struct disklabel *lp;
struct diskslices *ssp;
u_long ext_offset;
u_long ext_size;
u_long base_ext_offset;
int nsectors;
int ntracks;
u_long mbr_offset;
int level;
{
struct buf *bp;
u_char *cp;
int dospart;
struct dos_partition *dp;
struct dos_partition dpcopy[NDOSPART];
u_long ext_offsets[NDOSPART];
u_long ext_sizes[NDOSPART];
char partname[2];
int slice;
char *sname;
struct diskslice *sp;
if (level >= 16) {
printf(
"%s: excessive recursion in search for slices; aborting search\n",
devtoname(dev));
return;
}
/* Read extended boot record. */
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dev;
bp->b_blkno = ext_offset;
bp->b_bcount = lp->d_secsize;
bp->b_iocmd = BIO_READ;
DEV_STRATEGY(bp);
if (bufwait(bp) != 0) {
disk_err(&bp->b_io, "reading extended partition table: error",
0, 1);
goto done;
}
/* Weakly verify it. */
cp = bp->b_data;
if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART,
partname);
if (bootverbose)
printf("%s: invalid extended partition table: no magic\n",
sname);
goto done;
}
/* Make a copy of the partition table to avoid alignment problems. */
memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
slice = ssp->dss_nslices;
for (dospart = 0, dp = &dpcopy[0]; dospart < NDOSPART;
dospart++, dp++) {
ext_sizes[dospart] = 0;
if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
&& dp->dp_start == 0 && dp->dp_size == 0)
continue;
if (dp->dp_typ == DOSPTYP_EXTENDED ||
dp->dp_typ == DOSPTYP_EXTENDEDX) {
static char buf[32];
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
RAW_PART, partname);
snprintf(buf, sizeof(buf), "%s", sname);
if (strlen(buf) < sizeof buf - 11)
strcat(buf, "<extended>");
check_part(buf, dp, base_ext_offset, nsectors,
ntracks, mbr_offset);
ext_offsets[dospart] = base_ext_offset + dp->dp_start;
ext_sizes[dospart] = dp->dp_size;
} else {
sname = dsname(dev, dkunit(dev), slice, RAW_PART,
partname);
check_part(sname, dp, ext_offset, nsectors, ntracks,
mbr_offset);
if (slice >= MAX_SLICES) {
printf("%s: too many slices\n", sname);
slice++;
continue;
}
sp = &ssp->dss_slices[slice];
if (mbr_setslice(sname, lp, sp, dp, ext_offset) != 0)
continue;
slice++;
}
}
ssp->dss_nslices = slice;
/* If we found any more slices, recursively find all the subslices. */
for (dospart = 0; dospart < NDOSPART; dospart++)
if (ext_sizes[dospart] != 0)
mbr_extended(dev, lp, ssp, ext_offsets[dospart],
ext_sizes[dospart], base_ext_offset,
nsectors, ntracks, mbr_offset, ++level);
done:
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
}
static int
mbr_setslice(sname, lp, sp, dp, br_offset)
char *sname;
struct disklabel *lp;
struct diskslice *sp;
struct dos_partition *dp;
u_long br_offset;
{
u_long offset;
u_long size;
offset = br_offset + dp->dp_start;
if (offset > lp->d_secperunit || offset < br_offset) {
printf(
"%s: slice starts beyond end of the disk: rejecting it\n",
sname);
return (1);
}
size = lp->d_secperunit - offset;
if (size >= dp->dp_size)
size = dp->dp_size;
else
printf(
"%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n",
sname, (u_long)dp->dp_size, size);
sp->ds_offset = offset;
sp->ds_size = size;
sp->ds_type = dp->dp_typ;
#ifdef PC98_ATCOMPAT
/* Fake FreeBSD(98). */
if (sp->ds_type == DOSPTYP_386BSD)
sp->ds_type = 0x94;
#endif
#if 0
lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
#endif
return (0);
}
#endif

View File

@ -1,940 +0,0 @@
#ifdef NO_GEOM
/*-
* Copyright (c) 1994 Bruce D. Evans.
* All rights reserved.
*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* 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: @(#)wd.c 7.2 (Berkeley) 5/9/91
* from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
* 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 $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/diskslice.h>
#if defined(PC98) && !defined(PC98_ATCOMPAT)
#include <sys/diskpc98.h>
#else
#include <sys/diskmbr.h>
#endif
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/stdint.h>
#include <sys/syslog.h>
#include <sys/vnode.h>
#define TRACE(str) do { if (ds_debug) printf str; } while (0)
typedef u_char bool_t;
static volatile bool_t ds_debug;
static struct disklabel *clone_label(struct disklabel *lp);
static void dsiodone(struct bio *bp);
static char *fixlabel(char *sname, struct diskslice *sp,
struct disklabel *lp, int writeflag);
static void free_ds_label(struct diskslices *ssp, int slice);
static void partition_info(char *sname, int part, struct partition *pp);
static void slice_info(char *sname, struct diskslice *sp);
static void set_ds_label(struct diskslices *ssp, int slice,
struct disklabel *lp);
static void set_ds_labeldevs(dev_t dev, struct diskslices *ssp);
static void set_ds_wlabel(struct diskslices *ssp, int slice,
int wlabel);
/*
* Duplicate a label for the whole disk, and initialize defaults in the
* copy for fields that are not already initialized. The caller only
* needs to initialize d_secsize and d_secperunit, and zero the fields
* that are to be defaulted.
*/
static struct disklabel *
clone_label(lp)
struct disklabel *lp;
{
struct disklabel *lp1;
lp1 = malloc(sizeof *lp1, M_DEVBUF, 0);
*lp1 = *lp;
lp = NULL;
if (lp1->d_typename[0] == '\0')
strlcpy(lp1->d_typename, "amnesiac", sizeof(lp1->d_typename));
if (lp1->d_packname[0] == '\0')
strlcpy(lp1->d_packname, "fictitious", sizeof(lp1->d_packname));
if (lp1->d_nsectors == 0)
lp1->d_nsectors = 32;
if (lp1->d_ntracks == 0)
lp1->d_ntracks = 64;
lp1->d_secpercyl = lp1->d_nsectors * lp1->d_ntracks;
lp1->d_ncylinders = lp1->d_secperunit / lp1->d_secpercyl;
if (lp1->d_rpm == 0)
lp1->d_rpm = 3600;
if (lp1->d_interleave == 0)
lp1->d_interleave = 1;
if (lp1->d_npartitions < RAW_PART + 1)
lp1->d_npartitions = MAXPARTITIONS;
if (lp1->d_bbsize == 0)
lp1->d_bbsize = BBSIZE;
lp1->d_partitions[RAW_PART].p_size = lp1->d_secperunit;
lp1->d_magic = DISKMAGIC;
lp1->d_magic2 = DISKMAGIC;
lp1->d_checksum = dkcksum(lp1);
return (lp1);
}
dev_t
dkmodslice(dev_t dev, int slice)
{
return (makedev(major(dev), (minor(dev) & ~0x1f0000) | (slice << 16)));
}
u_int
dkunit(dev_t dev)
{
return (((minor(dev) >> 16) & 0x1e0) | ((minor(dev) >> 3) & 0x1f));
}
/*
* Determine the size of the transfer, and make sure it is
* within the boundaries of the partition. Adjust transfer
* if needed, and signal errors or early completion.
*
* XXX TODO:
* o Split buffers that are too big for the device.
* o Check for overflow.
* o Finish cleaning this up.
*/
int
dscheck(bp, ssp)
struct bio *bp;
struct diskslices *ssp;
{
daddr_t blkno;
daddr_t endsecno;
daddr_t labelsect;
struct disklabel *lp;
char *msg;
long nsec;
struct partition *pp;
daddr_t secno;
daddr_t slicerel_secno;
struct diskslice *sp;
blkno = bp->bio_blkno;
if (blkno < 0) {
printf("dscheck(%s): negative bio_blkno %ld\n",
devtoname(bp->bio_dev), (long)blkno);
bp->bio_error = EINVAL;
goto bad;
}
sp = &ssp->dss_slices[dkslice(bp->bio_dev)];
lp = sp->ds_label;
if (ssp->dss_secmult == 1) {
if (bp->bio_bcount % (u_long)DEV_BSIZE)
goto bad_bcount;
secno = blkno;
nsec = bp->bio_bcount >> DEV_BSHIFT;
} else if (ssp->dss_secshift != -1) {
if (bp->bio_bcount & (ssp->dss_secsize - 1))
goto bad_bcount;
if (blkno & (ssp->dss_secmult - 1))
goto bad_blkno;
secno = blkno >> ssp->dss_secshift;
nsec = bp->bio_bcount >> (DEV_BSHIFT + ssp->dss_secshift);
} else {
if (bp->bio_bcount % ssp->dss_secsize)
goto bad_bcount;
if (blkno % ssp->dss_secmult)
goto bad_blkno;
secno = blkno / ssp->dss_secmult;
nsec = bp->bio_bcount / ssp->dss_secsize;
}
if (lp == NULL) {
labelsect = -LABELSECTOR - 1;
endsecno = sp->ds_size;
slicerel_secno = secno;
} else {
labelsect = lp->d_partitions[LABEL_PART].p_offset;
if (labelsect != 0)
Debugger("labelsect != 0 in dscheck()");
pp = &lp->d_partitions[dkpart(bp->bio_dev)];
endsecno = pp->p_size;
slicerel_secno = pp->p_offset + secno;
}
/* overwriting disk label ? */
/* XXX should also protect bootstrap in first 8K */
if (slicerel_secno <= LABELSECTOR + labelsect &&
#if LABELSECTOR != 0
slicerel_secno + nsec > LABELSECTOR + labelsect &&
#endif
(bp->bio_cmd == BIO_WRITE) && sp->ds_wlabel == 0) {
bp->bio_error = EROFS;
goto bad;
}
#if defined(DOSBBSECTOR) && defined(notyet)
/* overwriting master boot record? */
if (slicerel_secno <= DOSBBSECTOR && (bp->bio_cmd == BIO_WRITE) &&
sp->ds_wlabel == 0) {
bp->bio_error = EROFS;
goto bad;
}
#endif
/* beyond partition? */
if ((uintmax_t)secno + nsec > endsecno) {
/* if exactly at end of disk, return an EOF */
if (secno == endsecno) {
bp->bio_resid = bp->bio_bcount;
return (0);
}
/* or truncate if part of it fits */
if (secno > endsecno) {
bp->bio_error = EINVAL;
goto bad;
}
bp->bio_bcount = (endsecno - secno) * ssp->dss_secsize;
}
bp->bio_pblkno = sp->ds_offset + slicerel_secno;
/*
* Snoop on label accesses if the slice offset is nonzero. Fudge
* offsets in the label to keep the in-core label coherent with
* the on-disk one.
*/
if (slicerel_secno <= LABELSECTOR + labelsect
#if LABELSECTOR != 0
&& slicerel_secno + nsec > LABELSECTOR + labelsect
#endif
&& sp->ds_offset != 0) {
struct iodone_chain *ic;
ic = malloc(sizeof *ic , M_DEVBUF, 0);
ic->ic_prev_flags = bp->bio_flags;
ic->ic_prev_iodone = bp->bio_done;
ic->ic_prev_iodone_chain = bp->bio_done_chain;
ic->ic_args[0].ia_long = (LABELSECTOR + labelsect -
slicerel_secno) * ssp->dss_secsize;
ic->ic_args[1].ia_ptr = sp;
bp->bio_done = dsiodone;
bp->bio_done_chain = ic;
if (!(bp->bio_cmd == BIO_READ)) {
/*
* XXX even disklabel(8) writes directly so we need
* to adjust writes. Perhaps we should drop support
* for DIOCWLABEL (always write protect labels) and
* require the use of DIOCWDINFO.
*
* XXX probably need to copy the data to avoid even
* temporarily corrupting the in-core copy.
*/
/* XXX need name here. */
msg = fixlabel((char *)NULL, sp,
(struct disklabel *)
(bp->bio_data + ic->ic_args[0].ia_long),
TRUE);
if (msg != NULL) {
printf("dscheck(%s): %s\n",
devtoname(bp->bio_dev), msg);
bp->bio_error = EROFS;
goto bad;
}
}
}
return (1);
bad_bcount:
printf(
"dscheck(%s): bio_bcount %ld is not on a sector boundary (ssize %d)\n",
devtoname(bp->bio_dev), bp->bio_bcount, ssp->dss_secsize);
bp->bio_error = EINVAL;
goto bad;
bad_blkno:
printf(
"dscheck(%s): bio_blkno %ld is not on a sector boundary (ssize %d)\n",
devtoname(bp->bio_dev), (long)blkno, ssp->dss_secsize);
bp->bio_error = EINVAL;
goto bad;
bad:
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
return (-1);
}
void
dsclose(dev, mode, ssp)
dev_t dev;
int mode;
struct diskslices *ssp;
{
u_char mask;
struct diskslice *sp;
sp = &ssp->dss_slices[dkslice(dev)];
mask = 1 << dkpart(dev);
sp->ds_openmask &= ~mask;
}
void
dsgone(sspp)
struct diskslices **sspp;
{
int slice;
struct diskslice *sp;
struct diskslices *ssp;
for (slice = 0, ssp = *sspp; slice < ssp->dss_nslices; slice++) {
sp = &ssp->dss_slices[slice];
free_ds_label(ssp, slice);
}
free(ssp, M_DEVBUF);
*sspp = NULL;
}
/*
* For the "write" commands (DIOCSDINFO and DIOCWDINFO), this
* is subject to the same restriction as dsopen().
*/
int
dsioctl(dev, cmd, data, flags, sspp)
dev_t dev;
u_long cmd;
caddr_t data;
int flags;
struct diskslices **sspp;
{
int error;
struct disklabel *lp;
int old_wlabel;
u_char openmask;
int part;
int slice;
struct diskslice *sp;
struct diskslices *ssp;
slice = dkslice(dev);
ssp = *sspp;
sp = &ssp->dss_slices[slice];
lp = sp->ds_label;
switch (cmd) {
case DIOCGDINFO:
if (lp == NULL)
return (EINVAL);
*(struct disklabel *)data = *lp;
return (0);
case DIOCGMEDIASIZE:
if (lp == NULL)
*(off_t *)data = (off_t)sp->ds_size * ssp->dss_secsize;
else
*(off_t *)data =
(off_t)lp->d_partitions[dkpart(dev)].p_size *
lp->d_secsize;
return (0);
case DIOCGSECTORSIZE:
*(u_int *)data = ssp->dss_secsize;
return (0);
case DIOCGSLICEINFO:
bcopy(ssp, data, (char *)&ssp->dss_slices[ssp->dss_nslices] -
(char *)ssp);
return (0);
case DIOCSDINFO:
if (slice == WHOLE_DISK_SLICE)
return (ENODEV);
if (!(flags & FWRITE))
return (EBADF);
lp = malloc(sizeof *lp, M_DEVBUF, 0);
if (sp->ds_label == NULL)
bzero(lp, sizeof *lp);
else
bcopy(sp->ds_label, lp, sizeof *lp);
if (sp->ds_label == NULL)
openmask = 0;
else {
openmask = sp->ds_openmask;
if (slice == COMPATIBILITY_SLICE)
openmask |= ssp->dss_slices[
ssp->dss_first_bsd_slice].ds_openmask;
else if (slice == ssp->dss_first_bsd_slice)
openmask |= ssp->dss_slices[
COMPATIBILITY_SLICE].ds_openmask;
}
error = setdisklabel(lp, (struct disklabel *)data,
(u_long)openmask);
/* XXX why doesn't setdisklabel() check this? */
if (error == 0 && lp->d_partitions[RAW_PART].p_offset != 0)
error = EXDEV;
if (error == 0) {
if (lp->d_secperunit > sp->ds_size)
error = ENOSPC;
for (part = 0; part < lp->d_npartitions; part++)
if (lp->d_partitions[part].p_size > sp->ds_size)
error = ENOSPC;
}
if (error != 0) {
free(lp, M_DEVBUF);
return (error);
}
free_ds_label(ssp, slice);
set_ds_label(ssp, slice, lp);
set_ds_labeldevs(dev, ssp);
return (0);
case DIOCSYNCSLICEINFO:
if (slice != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART)
return (EINVAL);
if (!*(int *)data)
for (slice = 0; slice < ssp->dss_nslices; slice++) {
openmask = ssp->dss_slices[slice].ds_openmask;
if (openmask
&& (slice != WHOLE_DISK_SLICE
|| openmask & ~(1 << RAW_PART)))
return (EBUSY);
}
/*
* Temporarily forget the current slices struct and read
* the current one.
* XXX should wait for current accesses on this disk to
* complete, then lock out future accesses and opens.
*/
*sspp = NULL;
lp = malloc(sizeof *lp, M_DEVBUF, 0);
*lp = *ssp->dss_slices[WHOLE_DISK_SLICE].ds_label;
error = dsopen(dev, S_IFCHR, ssp->dss_oflags, sspp, lp);
if (error != 0) {
free(lp, M_DEVBUF);
*sspp = ssp;
return (error);
}
/*
* Reopen everything. This is a no-op except in the "force"
* case and when the raw bdev and cdev are both open. Abort
* if anything fails.
*/
for (slice = 0; slice < ssp->dss_nslices; slice++) {
for (openmask = ssp->dss_slices[slice].ds_openmask,
part = 0; openmask; openmask >>= 1, part++) {
if (!(openmask & 1))
continue;
error = dsopen(dkmodslice(dkmodpart(dev, part),
slice),
S_IFCHR, ssp->dss_oflags, sspp,
lp);
if (error != 0) {
free(lp, M_DEVBUF);
*sspp = ssp;
return (EBUSY);
}
}
}
free(lp, M_DEVBUF);
dsgone(&ssp);
return (0);
case DIOCWDINFO:
error = dsioctl(dev, DIOCSDINFO, data, flags, &ssp);
if (error != 0)
return (error);
/*
* XXX this used to hack on dk_openpart to fake opening
* partition 0 in case that is used instead of dkpart(dev).
*/
old_wlabel = sp->ds_wlabel;
set_ds_wlabel(ssp, slice, TRUE);
error = writedisklabel(dev, sp->ds_label);
/* XXX should invalidate in-core label if write failed. */
set_ds_wlabel(ssp, slice, old_wlabel);
return (error);
case DIOCWLABEL:
#ifndef __alpha__
if (slice == WHOLE_DISK_SLICE)
return (ENODEV);
#endif
if (!(flags & FWRITE))
return (EBADF);
set_ds_wlabel(ssp, slice, *(int *)data != 0);
return (0);
default:
return (ENOIOCTL);
}
}
static void
dsiodone(bp)
struct bio *bp;
{
struct iodone_chain *ic;
char *msg;
ic = bp->bio_done_chain;
bp->bio_done = ic->ic_prev_iodone;
bp->bio_done_chain = ic->ic_prev_iodone_chain;
if (!(bp->bio_cmd == BIO_READ)
|| (!(bp->bio_flags & BIO_ERROR) && bp->bio_error == 0)) {
msg = fixlabel((char *)NULL, ic->ic_args[1].ia_ptr,
(struct disklabel *)
(bp->bio_data + ic->ic_args[0].ia_long),
FALSE);
if (msg != NULL)
printf("%s\n", msg);
}
free(ic, M_DEVBUF);
biodone(bp);
}
int
dsisopen(ssp)
struct diskslices *ssp;
{
int slice;
if (ssp == NULL)
return (0);
for (slice = 0; slice < ssp->dss_nslices; slice++)
if (ssp->dss_slices[slice].ds_openmask)
return (1);
return (0);
}
/*
* Allocate a slices "struct" and initialize it to contain only an empty
* compatibility slice (pointing to itself), a whole disk slice (covering
* the disk as described by the label), and (nslices - BASE_SLICES) empty
* slices beginning at BASE_SLICE.
*/
struct diskslices *
dsmakeslicestruct(nslices, lp)
int nslices;
struct disklabel *lp;
{
struct diskslice *sp;
struct diskslices *ssp;
ssp = malloc(offsetof(struct diskslices, dss_slices) +
nslices * sizeof *sp, M_DEVBUF, 0);
ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE;
ssp->dss_nslices = nslices;
ssp->dss_oflags = 0;
ssp->dss_secmult = lp->d_secsize / DEV_BSIZE;
if (ssp->dss_secmult & (ssp->dss_secmult - 1))
ssp->dss_secshift = -1;
else
ssp->dss_secshift = ffs(ssp->dss_secmult) - 1;
ssp->dss_secsize = lp->d_secsize;
sp = &ssp->dss_slices[0];
bzero(sp, nslices * sizeof *sp);
sp[WHOLE_DISK_SLICE].ds_size = lp->d_secperunit;
return (ssp);
}
char *
dsname(dev, unit, slice, part, partname)
dev_t dev;
int unit;
int slice;
int part;
char *partname;
{
static char name[32];
const char *dname;
dname = devsw(dev)->d_name;
if (strlen(dname) > 16)
dname = "nametoolong";
snprintf(name, sizeof(name), "%s%d", dname, unit);
partname[0] = '\0';
if (slice != WHOLE_DISK_SLICE || part != RAW_PART) {
partname[0] = 'a' + part;
partname[1] = '\0';
if (slice != COMPATIBILITY_SLICE)
snprintf(name + strlen(name),
sizeof(name) - strlen(name), "s%d", slice - 1);
}
return (name);
}
/*
* This should only be called when the unit is inactive and the strategy
* routine should not allow it to become active unless we call it. Our
* strategy routine must be special to allow activity.
*/
int
dsopen(dev, mode, flags, sspp, lp)
dev_t dev;
int mode;
u_int flags;
struct diskslices **sspp;
struct disklabel *lp;
{
dev_t dev1;
int error;
struct disklabel *lp1;
char *msg;
u_char mask;
int part;
char partname[2];
int slice;
char *sname;
struct diskslice *sp;
struct diskslices *ssp;
int unit;
dev->si_bsize_phys = lp->d_secsize;
unit = dkunit(dev);
if (lp->d_secsize % DEV_BSIZE) {
printf("%s: invalid sector size %lu\n", devtoname(dev),
(u_long)lp->d_secsize);
return (EINVAL);
}
/*
* XXX reinitialize the slice table unless there is an open device
* on the unit. This should only be done if the media has changed.
*/
ssp = *sspp;
if (!dsisopen(ssp)) {
if (ssp != NULL)
dsgone(sspp);
/*
* Allocate a minimal slices "struct". This will become
* the final slices "struct" if we don't want real slices
* or if we can't find any real slices.
*/
*sspp = dsmakeslicestruct(BASE_SLICE, lp);
TRACE(("dsinit\n"));
error = dsinit(dev, lp, sspp);
if (error != 0) {
dsgone(sspp);
return (error);
}
ssp = *sspp;
ssp->dss_oflags = flags;
/*
* If there are no real slices, then make the compatiblity
* slice cover the whole disk.
*/
if (ssp->dss_nslices == BASE_SLICE)
ssp->dss_slices[COMPATIBILITY_SLICE].ds_size
= lp->d_secperunit;
/* Point the compatibility slice at the BSD slice, if any. */
for (slice = BASE_SLICE; slice < ssp->dss_nslices; slice++) {
sp = &ssp->dss_slices[slice];
if (sp->ds_type == DOSPTYP_386BSD /* XXX */) {
ssp->dss_first_bsd_slice = slice;
ssp->dss_slices[COMPATIBILITY_SLICE].ds_offset
= sp->ds_offset;
ssp->dss_slices[COMPATIBILITY_SLICE].ds_size
= sp->ds_size;
ssp->dss_slices[COMPATIBILITY_SLICE].ds_type
= sp->ds_type;
break;
}
}
ssp->dss_slices[WHOLE_DISK_SLICE].ds_label = clone_label(lp);
ssp->dss_slices[WHOLE_DISK_SLICE].ds_wlabel = TRUE;
}
/* Initialize secondary info for all slices. */
for (slice = 0; slice < ssp->dss_nslices; slice++) {
sp = &ssp->dss_slices[slice];
if (sp->ds_label != NULL
#ifdef __alpha__
&& slice != WHOLE_DISK_SLICE
#endif
)
continue;
dev1 = dkmodslice(dkmodpart(dev, RAW_PART), slice);
#if 0
sname = dsname(dev, unit, slice, RAW_PART, partname);
#else
*partname='\0';
sname = dev1->si_name;
#endif
/*
* XXX this should probably only be done for the need_init
* case, but there may be a problem with DIOCSYNCSLICEINFO.
*/
set_ds_wlabel(ssp, slice, TRUE); /* XXX invert */
lp1 = clone_label(lp);
TRACE(("readdisklabel\n"));
msg = readdisklabel(dev1, lp1);
if (msg == NULL)
msg = fixlabel(sname, sp, lp1, FALSE);
if (msg == NULL && lp1->d_secsize != ssp->dss_secsize)
msg = "inconsistent sector size";
if (msg != NULL) {
if (sp->ds_type == DOSPTYP_386BSD /* XXX */)
log(LOG_WARNING, "%s: cannot find label (%s)\n",
sname, msg);
free(lp1, M_DEVBUF);
continue;
}
if (lp1->d_flags & D_BADSECT) {
log(LOG_ERR, "%s: bad sector table not supported\n",
sname);
free(lp1, M_DEVBUF);
continue;
}
set_ds_label(ssp, slice, lp1);
set_ds_labeldevs(dev1, ssp);
set_ds_wlabel(ssp, slice, FALSE);
}
slice = dkslice(dev);
if (slice >= ssp->dss_nslices)
return (ENXIO);
sp = &ssp->dss_slices[slice];
part = dkpart(dev);
if (part != RAW_PART
&& (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions))
return (EINVAL); /* XXX needs translation */
mask = 1 << part;
sp->ds_openmask |= mask;
return (0);
}
int
dssize(dev, sspp)
dev_t dev;
struct diskslices **sspp;
{
struct disklabel *lp;
int part;
int slice;
struct diskslices *ssp;
slice = dkslice(dev);
part = dkpart(dev);
ssp = *sspp;
if (ssp == NULL || slice >= ssp->dss_nslices
|| !(ssp->dss_slices[slice].ds_openmask & (1 << part))) {
if (devsw(dev)->d_open(dev, FREAD, S_IFCHR,
(struct thread *)NULL) != 0)
return (-1);
devsw(dev)->d_close(dev, FREAD, S_IFCHR, (struct thread *)NULL);
ssp = *sspp;
}
lp = ssp->dss_slices[slice].ds_label;
if (lp == NULL)
return (-1);
return ((int)lp->d_partitions[part].p_size);
}
static void
free_ds_label(ssp, slice)
struct diskslices *ssp;
int slice;
{
struct disklabel *lp;
struct diskslice *sp;
sp = &ssp->dss_slices[slice];
lp = sp->ds_label;
if (lp == NULL)
return;
free(lp, M_DEVBUF);
set_ds_label(ssp, slice, (struct disklabel *)NULL);
}
static char *
fixlabel(sname, sp, lp, writeflag)
char *sname;
struct diskslice *sp;
struct disklabel *lp;
int writeflag;
{
u_long end;
u_long offset;
int part;
struct partition *pp;
u_long start;
bool_t warned;
/* These errors "can't happen" so don't bother reporting details. */
if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC)
return ("fixlabel: invalid magic");
if (dkcksum(lp) != 0)
return ("fixlabel: invalid checksum");
pp = &lp->d_partitions[RAW_PART];
if (writeflag) {
start = 0;
offset = sp->ds_offset;
} else {
start = sp->ds_offset;
offset = -sp->ds_offset;
}
if (pp->p_offset != start) {
if (sname != NULL) {
printf(
"%s: rejecting BSD label: raw partition offset != slice offset\n",
sname);
slice_info(sname, sp);
partition_info(sname, RAW_PART, pp);
}
return ("fixlabel: raw partition offset != slice offset");
}
if (pp->p_size != sp->ds_size) {
if (sname != NULL) {
printf("%s: raw partition size != slice size\n", sname);
slice_info(sname, sp);
partition_info(sname, RAW_PART, pp);
}
if (pp->p_size > sp->ds_size) {
if (sname == NULL)
return ("fixlabel: raw partition size > slice size");
printf("%s: truncating raw partition\n", sname);
pp->p_size = sp->ds_size;
}
}
end = start + sp->ds_size;
if (start > end)
return ("fixlabel: slice wraps");
if (lp->d_secpercyl <= 0)
return ("fixlabel: d_secpercyl <= 0");
pp -= RAW_PART;
warned = FALSE;
for (part = 0; part < lp->d_npartitions; part++, pp++) {
if (pp->p_offset != 0 || pp->p_size != 0) {
if (pp->p_offset < start
|| pp->p_offset + pp->p_size > end
|| pp->p_offset + pp->p_size < pp->p_offset) {
if (sname != NULL) {
printf(
"%s: rejecting partition in BSD label: it isn't entirely within the slice\n",
sname);
if (!warned) {
slice_info(sname, sp);
warned = TRUE;
}
partition_info(sname, part, pp);
}
/* XXX else silently discard junk. */
bzero(pp, sizeof *pp);
} else
pp->p_offset += offset;
}
}
lp->d_ncylinders = sp->ds_size / lp->d_secpercyl;
lp->d_secperunit = sp->ds_size;
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
return (NULL);
}
static void
partition_info(sname, part, pp)
char *sname;
int part;
struct partition *pp;
{
printf("%s%c: start %lu, end %lu, size %lu\n", sname, 'a' + part,
(u_long)pp->p_offset, (u_long)(pp->p_offset + pp->p_size - 1),
(u_long)pp->p_size);
}
static void
slice_info(sname, sp)
char *sname;
struct diskslice *sp;
{
printf("%s: start %lu, end %lu, size %lu\n", sname,
sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size);
}
static void
set_ds_label(ssp, slice, lp)
struct diskslices *ssp;
int slice;
struct disklabel *lp;
{
ssp->dss_slices[slice].ds_label = lp;
if (slice == COMPATIBILITY_SLICE)
ssp->dss_slices[ssp->dss_first_bsd_slice].ds_label = lp;
else if (slice == ssp->dss_first_bsd_slice)
ssp->dss_slices[COMPATIBILITY_SLICE].ds_label = lp;
}
static void
set_ds_labeldevs(dev, ssp)
dev_t dev;
struct diskslices *ssp;
{
}
static void
set_ds_wlabel(ssp, slice, wlabel)
struct diskslices *ssp;
int slice;
int wlabel;
{
ssp->dss_slices[slice].ds_wlabel = wlabel;
if (slice == COMPATIBILITY_SLICE)
ssp->dss_slices[ssp->dss_first_bsd_slice].ds_wlabel = wlabel;
else if (slice == ssp->dss_first_bsd_slice)
ssp->dss_slices[COMPATIBILITY_SLICE].ds_wlabel = wlabel;
}
#endif

View File

@ -1,404 +0,0 @@
#ifdef NO_GEOM
/*-
* 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 $
* $FreeBSD$
*/
/*
* PC9801 port by KATO Takenor <kato@eclogite.eps.nagoya-u.ac.jp>
*/
#include "compat_atdisk.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#if defined(PC98) && !defined(PC98_ATCOMPAT)
#include <sys/diskpc98.h>
#else
#include <sys/diskmbr.h>
#endif
#include <sys/diskslice.h>
#include <sys/malloc.h>
#include <sys/syslog.h>
#define TRACE(str) do { if (dsi_debug) printf str; } while (0)
static volatile u_char dsi_debug;
static int check_part(char *sname, struct pc98_partition *dp,
u_long offset, int nsectors, int ntracks,
u_long mbr_offset);
static int mbr_setslice(char *sname, struct disklabel *lp,
struct diskslice *sp, struct pc98_partition *dp,
u_long br_offset);
#define DPBLKNO(cyl,hd,sect) ((cyl)*(lp->d_secpercyl))
#if NCOMPAT_ATDISK > 0
int atcompat_dsinit(dev_t dev,
struct disklabel *lp, struct diskslices **sspp);
#endif
static int
check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
char *sname;
struct pc98_partition *dp;
u_long offset;
int nsectors;
int ntracks;
u_long mbr_offset;
{
int chs_ecyl;
int chs_esect;
int chs_scyl;
int chs_ssect;
int error;
u_long esector;
u_long esector1;
u_long secpercyl;
u_long ssector;
u_long ssector1;
u_long pc98_start;
u_long pc98_size;
secpercyl = (u_long)nsectors * ntracks;
chs_scyl = dp->dp_scyl;
chs_ssect = dp->dp_ssect;
ssector = chs_ssect + dp->dp_shd * nsectors +
chs_scyl * secpercyl + mbr_offset;
pc98_start = dp->dp_scyl * secpercyl;
pc98_size = dp->dp_ecyl ?
(dp->dp_ecyl + 1) * secpercyl - pc98_start : 0;
ssector1 = offset + pc98_start;
/*
* If ssector1 is on a cylinder >= 1024, then ssector can't be right.
* Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
* apart from the cylinder being reduced modulo 1024. Always allow
* 1023/255/63.
*/
if ((ssector < ssector1
&& ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
&& chs_scyl == 1023)
|| (secpercyl != 0
&& (ssector1 - ssector) % (1024 * secpercyl) == 0)))
|| (dp->dp_scyl == 255 && dp->dp_shd == 255
&& dp->dp_ssect == 255)) {
TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
ssector = ssector1;
}
chs_ecyl = dp->dp_ecyl;
chs_esect = nsectors - 1;
esector = chs_esect + (ntracks - 1) * nsectors +
chs_ecyl * secpercyl + mbr_offset;
esector1 = ssector1 + pc98_size - 1;
/* Allow certain bogus C/H/S values for esector, as above. */
if ((esector < esector1
&& ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
&& chs_ecyl == 1023)
|| (secpercyl != 0
&& (esector1 - esector) % (1024 * secpercyl) == 0)))
|| (dp->dp_ecyl == 255 && dp->dp_ehd == 255
&& dp->dp_esect == 255)) {
TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
esector = esector1;
}
error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
if (bootverbose)
printf("%s: mid 0x%x, start %lu, end = %lu, size %lu%s\n",
sname, dp->dp_mid, ssector1, esector1, pc98_size,
error ? "" : ": OK");
if (ssector != ssector1 && bootverbose)
printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
sname, chs_scyl, dp->dp_shd, chs_ssect,
ssector, ssector1);
if (esector != esector1 && bootverbose)
printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
sname, chs_ecyl, dp->dp_ehd, chs_esect,
esector, esector1);
return (error);
}
int
dsinit(dev, lp, sspp)
dev_t dev;
struct disklabel *lp;
struct diskslices **sspp;
{
struct buf *bp;
u_char *cp;
int dospart;
struct pc98_partition *dp;
struct pc98_partition *dp0;
int error;
int max_ncyls;
int max_nsectors;
int max_ntracks;
u_long mbr_offset;
char partname[2];
u_long secpercyl;
char *sname;
struct diskslice *sp;
struct diskslices *ssp;
mbr_offset = DOSBBSECTOR;
/* Read master boot record. */
if ((int)lp->d_secsize < 1024)
bp = geteblk((int)1024);
else
bp = geteblk((int)lp->d_secsize);
bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
bp->b_blkno = mbr_offset;
bp->b_bcount = lp->d_secsize;
bp->b_iocmd = BIO_READ;
if (bp->b_bcount < 1024)
bp->b_bcount = 1024;
DEV_STRATEGY(bp);
if (bufwait(bp) != 0) {
disk_err(&bp->b_io, "reading primary partition table: error",
0, 1);
error = EIO;
goto done;
}
/* Weakly verify it. */
cp = bp->b_data;
sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
if (bootverbose)
printf("%s: invalid primary partition table: no magic\n",
sname);
error = EINVAL;
goto done;
}
/*
* entire disk for FreeBSD
*/
if ((*(cp + 512) == 0x57) && (*(cp + 513) == 0x45) &&
(*(cp + 514) == 0x56) && (*(cp + 515) == 0x82)) {
sname = dsname(dev, dkunit(dev), BASE_SLICE,
RAW_PART, partname);
free(*sspp, M_DEVBUF);
ssp = dsmakeslicestruct(MAX_SLICES, lp);
*sspp = ssp;
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
sp->ds_offset = 0;
sp->ds_size = lp->d_secperunit;
sp->ds_type = DOSPTYP_386BSD;
sp->ds_subtype = 0xc4;
error = 0;
ssp->dss_nslices = BASE_SLICE + 1;
goto done;
}
/*
* XXX --- MS-DOG MO
*/
if ((*(cp + 0x0e) == 1) && (*(cp + 0x15) == 0xf0) &&
(*(cp + 0x1c) == 0x0) &&
((*(cp + 512) == 0xf0) || (*(cp + 512) == 0xf8)) &&
(*(cp + 513) == 0xff) && (*(cp + 514) == 0xff)) {
sname = dsname(dev, dkunit(dev), BASE_SLICE,
RAW_PART, partname);
free(*sspp, M_DEVBUF);
ssp = dsmakeslicestruct(MAX_SLICES, lp);
*sspp = ssp;
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
sp->ds_offset = 0;
sp->ds_size = lp->d_secperunit;
sp->ds_type = 0xa0; /* XXX */
sp->ds_subtype = 0x81; /* XXX */
error = 0;
ssp->dss_nslices = BASE_SLICE + 1;
goto done;
}
#if NCOMPAT_ATDISK > 0
/*
* Check magic number of 'extended format' for PC-9801.
* If no magic, it may be formatted on IBM-PC.
*/
if (((cp[4] != 'I') || (cp[5] != 'P') || (cp[6] != 'L') ||
(cp[7] != '1')) &&
((strncmp(devtoname(bp->b_dev), "da", 2) == 0) ||
(strncmp(devtoname(bp->b_dev), "wd", 2) == 0) ||
(strncmp(devtoname(bp->b_dev), "ad", 2) == 0))) {
/* IBM-PC HDD */
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
return atcompat_dsinit(dev, lp, sspp);
}
#endif
dp0 = (struct pc98_partition *)(cp + 512);
/* Guess the geometry. */
/*
* TODO:
* Perhaps skip entries with 0 size.
* Perhaps only look at entries of type DOSPTYP_386BSD.
*/
max_ncyls = 0;
max_nsectors = 0;
max_ntracks = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
int ncyls;
int nsectors;
int ntracks;
ncyls = lp->d_ncylinders;
if (max_ncyls < ncyls)
max_ncyls = ncyls;
nsectors = lp->d_nsectors;
if (max_nsectors < nsectors)
max_nsectors = nsectors;
ntracks = lp->d_ntracks;
if (max_ntracks < ntracks)
max_ntracks = ntracks;
}
/*
* Check that we have guessed the geometry right by checking the
* partition entries.
*/
/*
* TODO:
* As above.
* Check for overlaps.
* Check against d_secperunit if the latter is reliable.
*/
error = 0;
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0)
continue;
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
/*
* Temporarily ignore errors from this check. We could
* simplify things by accepting the table eariler if we
* always ignore errors here. Perhaps we should always
* accept the table if the magic is right but not let
* bad entries affect the geometry.
*/
check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
mbr_offset);
}
if (error != 0)
goto done;
/*
* Accept the DOS partition table.
* First adjust the label (we have been careful not to change it
* before we can guarantee success).
*/
secpercyl = (u_long)max_nsectors * max_ntracks;
if (secpercyl != 0) {
lp->d_nsectors = max_nsectors;
lp->d_ntracks = max_ntracks;
lp->d_secpercyl = secpercyl;
lp->d_ncylinders = lp->d_secperunit / secpercyl;
}
/*
* We are passed a pointer to a suitably initialized minimal
* slices "struct" with no dangling pointers in it. Replace it
* by a maximal one. This usually oversizes the "struct", but
* enlarging it while searching for logical drives would be
* inconvenient.
*/
free(*sspp, M_DEVBUF);
ssp = dsmakeslicestruct(MAX_SLICES, lp);
*sspp = ssp;
/* Initialize normal slices. */
sp = &ssp->dss_slices[BASE_SLICE];
for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
RAW_PART, partname);
(void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
}
ssp->dss_nslices = BASE_SLICE + NDOSPART;
done:
bp->b_flags |= B_INVAL | B_AGE;
brelse(bp);
if (error == EINVAL)
error = 0;
return (error);
}
static int
mbr_setslice(sname, lp, sp, dp, br_offset)
char *sname;
struct disklabel *lp;
struct diskslice *sp;
struct pc98_partition *dp;
u_long br_offset;
{
u_long offset;
u_long size;
offset = DPBLKNO(dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
size = dp->dp_ecyl ?
DPBLKNO(dp->dp_ecyl + 1, dp->dp_ehd, dp->dp_esect) - offset : 0;
sp->ds_offset = offset;
sp->ds_size = size;
sp->ds_type = dp->dp_mid;
sp->ds_subtype = dp->dp_sid;
strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name));
#if 0
lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
#endif
return (0);
}
#endif