aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_disklabel.c
diff options
context:
space:
mode:
authorRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-25 09:21:21 +0000
committerRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-25 09:21:21 +0000
commit26f9a76710a312a951848542b9ca1f44100450e2 (patch)
tree9179427ac860211c445df663fd2b86267366bfba /sys/kern/subr_disklabel.c
parentdbda0ec78e324aced444959e2c98b89b79f22812 (diff)
downloadsrc-26f9a76710a312a951848542b9ca1f44100450e2.tar.gz
src-26f9a76710a312a951848542b9ca1f44100450e2.zip
The big 4.4BSD Lite to FreeBSD 2.0.0 (Development) patch.
Reviewed by: Rodney W. Grimes Submitted by: John Dyson and David Greenman
Notes
Notes: svn path=/head/; revision=1549
Diffstat (limited to 'sys/kern/subr_disklabel.c')
-rw-r--r--sys/kern/subr_disklabel.c105
1 files changed, 101 insertions, 4 deletions
diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c
index 78dede4da773..cc0f28d37f15 100644
--- a/sys/kern/subr_disklabel.c
+++ b/sys/kern/subr_disklabel.c
@@ -43,6 +43,7 @@
#include <sys/buf.h>
#include <sys/disklabel.h>
#include <sys/syslog.h>
+#include <sys/dkbad.h>
/*
* Seek sort for disks. We depend on the driver which calls us using b_resid
@@ -153,14 +154,19 @@ insert: bp->b_actf = bq->b_actf;
* string on failure.
*/
char *
-readdisklabel(dev, strat, lp)
+readdisklabel(dev, strat, lp, dp, bdp)
dev_t dev;
int (*strat)();
register struct disklabel *lp;
+ struct dos_partition *dp;
+ struct dkbad *bdp;
{
register struct buf *bp;
struct disklabel *dlp;
char *msg = NULL;
+ int dospartoff;
+ int i;
+ int cyl;
if (lp->d_secperunit == 0)
lp->d_secperunit = 0x1fffffff;
@@ -170,11 +176,61 @@ readdisklabel(dev, strat, lp)
lp->d_partitions[0].p_offset = 0;
bp = geteblk((int)lp->d_secsize);
- bp->b_dev = dev;
- bp->b_blkno = LABELSECTOR;
+ /* do dos partitions in the process of getting disklabel? */
+ dospartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+ if (dp) {
+ struct dos_partition *ap;
+
+ /* read master boot record */
+ bp->b_dev = dev;
+ 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 done;
+ } else {
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_un.b_addr + DOSPARTOFF, dp,
+ NDOSPART * sizeof(*dp));
+ for (i = 0; i < NDOSPART; i++, dp++)
+ /* is this ours? */
+ if (dp->dp_size &&
+ dp->dp_typ == DOSPTYP_386BSD
+ && dospartoff == 0) {
+
+ /* need sector address for SCSI/IDE,
+ cylinder for ESDI/ST506/RLL */
+ dospartoff = dp->dp_start;
+ cyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
+
+ /* update disklabel with details */
+ lp->d_partitions[0].p_size =
+ dp->dp_size;
+ lp->d_partitions[0].p_offset =
+ dp->dp_start;
+ lp->d_ntracks = dp->dp_ehd + 1;
+ lp->d_nsectors = DPSECT(dp->dp_esect);
+ lp->d_subtype |= (lp->d_subtype & 3)
+ + i | DSTYPE_INDOSPART;
+ lp->d_secpercyl = lp->d_ntracks *
+ lp->d_nsectors;
+ }
+ }
+
+ }
+
+ /* next, dig out disk label */
+ bp->b_blkno = dospartoff + LABELSECTOR;
+ bp->b_dev = dev;
bp->b_bcount = lp->d_secsize;
bp->b_flags = B_BUSY | B_READ;
- bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
+ bp->b_cylinder = cyl;
(*strat)(bp);
if (biowait(bp))
msg = "I/O error";
@@ -194,6 +250,46 @@ readdisklabel(dev, strat, lp)
break;
}
}
+ if (msg)
+ goto done;
+
+ /* obtain bad sector table if requested and present */
+ if (bdp && (lp->d_flags & D_BADSECT)) {
+ struct dkbad *db;
+
+ printf("d_secsize: %d\n", lp->d_secsize);
+ i = 0;
+ do {
+ /* read a bad sector table */
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
+ if (lp->d_secsize > DEV_BSIZE)
+ bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
+ else
+ bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_cylinder = lp->d_ncylinders - 1;
+ (*strat)(bp);
+
+ /* if successful, validate, otherwise try another */
+ if (biowait(bp)) {
+ msg = "bad sector table I/O error";
+ } else {
+ db = (struct dkbad *)(bp->b_un.b_addr);
+#define DKBAD_MAGIC 0x4321
+ if (db->bt_mbz == 0
+ && db->bt_flag == DKBAD_MAGIC) {
+ msg = NULL;
+ *bdp = *db;
+ break;
+ } else
+ msg = "bad sector table corrupted";
+ }
+ } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
+ i < lp->d_nsectors);
+ }
+
+done:
bp->b_flags = B_INVAL | B_AGE;
brelse(bp);
return (msg);
@@ -294,6 +390,7 @@ done:
/*
* Compute checksum for disk label.
*/
+int
dkcksum(lp)
register struct disklabel *lp;
{