summaryrefslogtreecommitdiff
path: root/sys/arch/sparc
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-06-17 00:27:31 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-06-17 00:27:31 +0000
commit81f9f199b5e2a6741e5a9a68d39dd00dadaa4e18 (patch)
treeaa5797e58e49aa5ab1063818eacfa236c19c2adf /sys/arch/sparc
parent49e31b3e7fe854aae88f968da9911e2a4fd5d878 (diff)
significantly simplified disklabel infrastructure. MBR handling becomes MI
to support hotplug media on most architectures. disklabel setup and verification done using new helper functions. Disklabels must *always* have a correct checksum now. Same code paths are used to learn on-disk location disklabels, to avoid new errors sneaking in. Tested on almost all cases, testing help from todd, kettenis, krw, otto, dlg, robert, gwk, drahn
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r--sys/arch/sparc/include/disklabel.h4
-rw-r--r--sys/arch/sparc/sparc/disksubr.c120
2 files changed, 44 insertions, 80 deletions
diff --git a/sys/arch/sparc/include/disklabel.h b/sys/arch/sparc/include/disklabel.h
index 9c9b28b1e1a..d7021e04b65 100644
--- a/sys/arch/sparc/include/disklabel.h
+++ b/sys/arch/sparc/include/disklabel.h
@@ -1,5 +1,4 @@
-/* $OpenBSD: disklabel.h,v 1.2 1996/09/12 04:33:27 downsj Exp $ */
-/* $NetBSD: disklabel.h,v 1.4 1995/09/01 17:20:31 pk Exp $ */
+/* $OpenBSD: disklabel.h,v 1.3 2007/06/17 00:27:28 deraadt Exp $ */
/*
* Copyright (c) 1994 Christopher G. Demetriou
@@ -37,7 +36,6 @@
#define LABELSECTOR 0 /* sector containing label */
#define LABELOFFSET 64 /* offset of label in sector */
#define MAXPARTITIONS 16 /* number of partitions */
-#define RAW_PART 2 /* raw partition: xx?c */
struct cpu_disklabel {
char cd_block[512];
diff --git a/sys/arch/sparc/sparc/disksubr.c b/sys/arch/sparc/sparc/disksubr.c
index e4d23d91ea2..c37f39a5bb2 100644
--- a/sys/arch/sparc/sparc/disksubr.c
+++ b/sys/arch/sparc/sparc/disksubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disksubr.c,v 1.63 2007/06/14 03:41:22 deraadt Exp $ */
+/* $OpenBSD: disksubr.c,v 1.64 2007/06/17 00:27:29 deraadt Exp $ */
/* $NetBSD: disksubr.c,v 1.16 1996/04/28 20:25:59 thorpej Exp $ */
/*
@@ -46,8 +46,8 @@
#include "cd.h"
-static char *disklabel_sun_to_bsd(char *, struct disklabel *);
-static int disklabel_bsd_to_sun(struct disklabel *, char *);
+static char *disklabel_sun_to_bsd(struct sun_disklabel *, struct disklabel *);
+static int disklabel_bsd_to_sun(struct disklabel *, struct sun_disklabel *);
static __inline u_int sun_extended_sum(struct sun_disklabel *, void *);
#if NCD > 0
@@ -68,39 +68,21 @@ extern void cdstrategy(struct buf *);
*/
char *
readdisklabel(dev_t dev, void (*strat)(struct buf *),
- struct disklabel *lp, struct cpu_disklabel *clp, int spoofonly)
+ struct disklabel *lp, struct cpu_disklabel *osdep, int spoofonly)
{
- struct buf *bp = NULL;
- struct disklabel *dlp;
struct sun_disklabel *slp;
- char *msg = NULL;
- int error, i;
-
- /* minimal requirements for archetypal disk label */
- if (lp->d_secsize < DEV_BSIZE)
- lp->d_secsize = DEV_BSIZE;
- if (DL_GETDSIZE(lp) == 0)
- DL_SETDSIZE(lp, MAXDISKSIZE);
- if (lp->d_secpercyl == 0) {
- msg = "invalid geometry";
- goto done;
- }
- lp->d_npartitions = RAW_PART+1;
- for (i = 0; i < RAW_PART; i++) {
- DL_SETPSIZE(&lp->d_partitions[i], 0);
- DL_SETPOFFSET(&lp->d_partitions[i], 0);
- }
- if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
- DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
- DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
- lp->d_version = 1;
- lp->d_bbsize = 8192;
- lp->d_sbsize = 64*1024; /* XXX ? */
+ struct buf *bp = NULL;
+ char *msg;
- /* don't read the on-disk label if we are in spoofed-only mode */
- if (spoofonly)
+ if ((msg = initdisklabel(lp)))
goto done;
+ /*
+ * On sparc64 we check for a CD label first, because our
+ * CD install media contains both sparc & sparc64 labels.
+ * We want the sparc64 machine to find the "CD label", not
+ * the SunOS label, for loading it's kernel.
+ */
#if NCD > 0
if (strat == cdstrategy) {
#if defined(CD9660)
@@ -118,47 +100,42 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *),
}
#endif /* NCD > 0 */
- /* obtain buffer to probe drive with */
+ /* obtain buffer and initialize it */
bp = geteblk((int)lp->d_secsize);
-
- /* next, dig out disk label */
bp->b_dev = dev;
+
+ if (spoofonly)
+ goto doslabel;
+
bp->b_blkno = LABELSECTOR;
bp->b_cylinder = 0;
bp->b_bcount = lp->d_secsize;
bp->b_flags = B_BUSY | B_READ;
(*strat)(bp);
-
- /* if successful, locate disk label within block and validate */
- error = biowait(bp);
- if (error == 0) {
- /* Save the whole block in case it has info we need. */
- bcopy(bp->b_data, clp->cd_block, sizeof(clp->cd_block));
- }
- if (error) {
+ if (biowait(bp)) {
msg = "disk label read error";
goto done;
}
- slp = (struct sun_disklabel *)clp->cd_block;
+ /* XXX because xd(4) & xy(4) still need it */
+ bcopy(bp->b_data, osdep->cd_block, sizeof(osdep->cd_block));
+
+ slp = (struct sun_disklabel *)bp->b_data;
if (slp->sl_magic == SUN_DKMAGIC) {
- msg = disklabel_sun_to_bsd(clp->cd_block, lp);
+ msg = disklabel_sun_to_bsd(slp, lp);
goto done;
}
- /* Check for a native disk label (PROM can not boot it). */
- dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET);
- if (dlp->d_magic == DISKMAGIC) {
- if (dkcksum(dlp)) {
- msg = "disk label corrupted";
- goto done;
- }
- DL_SETDSIZE(dlp, DL_GETDSIZE(lp));
- *lp = *dlp; /* struct assignment */
- msg = NULL;
+ msg = checkdisklabel(bp->b_data + LABELOFFSET, lp);
+ if (msg == NULL)
goto done;
- }
+doslabel:
+ msg = readdoslabel(bp, strat, lp, osdep, NULL, NULL, spoofonly);
+ if (msg == NULL)
+ goto done;
+
+ /* A CD9660/UDF label may be on a non-CD drive, so recheck */
#if defined(CD9660)
if (iso_disklabelspoof(dev, strat, lp) == 0) {
msg = NULL;
@@ -171,39 +148,34 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *),
goto done;
}
#endif
- bzero(clp->cd_block, sizeof(clp->cd_block));
- msg = "no disk label";
done:
if (bp) {
bp->b_flags |= B_INVAL;
brelse(bp);
}
- disklabeltokernlabel(lp);
return (msg);
}
/*
* Write disk label back to device after modification.
- * Current label is already in clp->cd_block[]
*/
int
writedisklabel(dev_t dev, void (*strat)(struct buf *),
- struct disklabel *lp, struct cpu_disklabel *clp)
+ struct disklabel *lp, struct cpu_disklabel *osdep)
{
struct buf *bp = NULL;
int error;
- error = disklabel_bsd_to_sun(lp, clp->cd_block);
+ /* obtain buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ error = disklabel_bsd_to_sun(lp, (struct sun_disklabel *)bp->b_data);
if (error)
goto done;
- /* Get a buffer and copy the new label into it. */
- bp = geteblk((int)lp->d_secsize);
- bcopy(clp->cd_block, bp->b_data, sizeof(clp->cd_block));
-
/* Write out the updated label. */
- bp->b_dev = dev;
bp->b_blkno = LABELSECTOR;
bp->b_cylinder = 0;
bp->b_bcount = lp->d_secsize;
@@ -272,20 +244,16 @@ sun_extended_sum(struct sun_disklabel *sl, void *end)
* The BSD label is cleared out before this is called.
*/
static char *
-disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
+disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
{
- struct sun_disklabel *sl;
struct partition *npp;
struct sun_dkpart *spp;
int i, secpercyl;
- u_short cksum, *sp1, *sp2;
-
- sl = (struct sun_disklabel *)cp;
+ u_short cksum = 0, *sp1, *sp2;
/* Verify the XOR check. */
sp1 = (u_short *)sl;
sp2 = (u_short *)(sl + 1);
- cksum = 0;
while (sp1 < sp2)
cksum ^= *sp1++;
if (cksum != 0)
@@ -294,6 +262,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
/* Format conversion. */
lp->d_magic = DISKMAGIC;
lp->d_magic2 = DISKMAGIC;
+ lp->d_flags = D_VENDOR;
memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
lp->d_secsize = 512;
@@ -305,7 +274,7 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
lp->d_secpercyl = secpercyl;
if (DL_GETDSIZE(lp) == 0)
DL_SETDSIZE(lp, (daddr64_t)secpercyl * sl->sl_ncylinders);
- lp->d_version = 1; /* 48 bit addressing */
+ lp->d_version = 1;
lp->d_sparespercyl = sl->sl_sparespercyl;
lp->d_acylinders = sl->sl_acylinders;
@@ -396,9 +365,8 @@ disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
* Returns zero or error code.
*/
static int
-disklabel_bsd_to_sun(struct disklabel *lp, char *cp)
+disklabel_bsd_to_sun(struct disklabel *lp, struct sun_disklabel *sl)
{
- struct sun_disklabel *sl;
struct partition *npp;
struct sun_dkpart *spp;
int i, secpercyl;
@@ -408,8 +376,6 @@ disklabel_bsd_to_sun(struct disklabel *lp, char *cp)
if (lp->d_secsize != 512 || lp->d_nsectors == 0 || lp->d_ntracks == 0)
return (EINVAL);
- sl = (struct sun_disklabel *)cp;
-
/* Format conversion. */
memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
sl->sl_rpm = lp->d_rpm;