diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2000-07-02 17:51:36 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2000-07-02 17:51:36 +0000 |
commit | e22d5e7aa2374bf95f15cfeb9f2757b99170fa86 (patch) | |
tree | d4a0d975c31aecfc739b5ed5208d7cd1a38d2aa9 /sys/arch/sun3 | |
parent | bb13cce4ae3bb5e97e20cdcdd7dcd51372761860 (diff) |
Recognize and support 16 partition disklabels (taken from sparc port)
Diffstat (limited to 'sys/arch/sun3')
-rw-r--r-- | sys/arch/sun3/include/disklabel.h | 4 | ||||
-rw-r--r-- | sys/arch/sun3/include/sun_disklabel.h | 14 | ||||
-rw-r--r-- | sys/arch/sun3/sun3/disksubr.c | 185 |
3 files changed, 155 insertions, 48 deletions
diff --git a/sys/arch/sun3/include/disklabel.h b/sys/arch/sun3/include/disklabel.h index 5ca0f1f8b55..bf115738433 100644 --- a/sys/arch/sun3/include/disklabel.h +++ b/sys/arch/sun3/include/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.4 1997/09/21 04:21:07 niklas Exp $ */ +/* $OpenBSD: disklabel.h,v 1.5 2000/07/02 17:51:12 miod Exp $ */ /* $NetBSD: disklabel.h,v 1.3 1995/11/10 22:05:52 gwr Exp $ */ /* @@ -36,7 +36,7 @@ #define LABELSECTOR 0 /* sector containing label */ #define LABELOFFSET 64 /* offset of label in sector */ -#define MAXPARTITIONS 8 /* number of partitions */ +#define MAXPARTITIONS 16 /* number of partitions */ #define RAW_PART 2 /* raw partition: xx?c */ /* diff --git a/sys/arch/sun3/include/sun_disklabel.h b/sys/arch/sun3/include/sun_disklabel.h index 204e5dd8dba..dab09cad9ca 100644 --- a/sys/arch/sun3/include/sun_disklabel.h +++ b/sys/arch/sun3/include/sun_disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sun_disklabel.h,v 1.3 1997/09/21 04:21:23 niklas Exp $ */ +/* $OpenBSD: sun_disklabel.h,v 1.4 2000/07/02 17:51:12 miod Exp $ */ /* $NetBSD: sun_disklabel.h,v 1.4 1996/11/20 18:57:19 gwr Exp $ */ /* @@ -59,11 +59,17 @@ struct sun_dkpart { long sdkp_nsectors; /* number of sectors */ }; +#define SUNXPART 8 +#define SL_XPMAG (0x199d1fe2+SUNXPART) + struct sun_disklabel { /* total size = 512 bytes */ char sl_text[128]; - char sl_xxx1[292]; + u_long sl_xpsum; /* additive cksum, [sl_xpmag,sl_xxx1) */ + u_long sl_xpmag; /* "extended" magic number */ + struct sun_dkpart sl_xpart[SUNXPART]; /* "extended" partitions, i through p */ + char sl_xxx1[292-8-(8*SUNXPART)]; /* [292] including sl_x* */ u_short sl_rpm; /* rotational speed */ - u_short sl_pcyl; /* physical cylinders */ + u_short sl_pcylinders; /* number of physical cyls */ u_short sl_sparespercyl; /* spare sectors per cylinder */ u_short sl_xxx3[2]; u_short sl_interleave; /* interleave factor */ @@ -76,3 +82,5 @@ struct sun_disklabel { /* total size = 512 bytes */ u_short sl_magic; /* == SUN_DKMAGIC */ u_short sl_cksum; /* xor checksum of all shorts */ }; + +#define SUN_LABELOFFSET 128 diff --git a/sys/arch/sun3/sun3/disksubr.c b/sys/arch/sun3/sun3/disksubr.c index 52ca08c1b23..44ce10392a9 100644 --- a/sys/arch/sun3/sun3/disksubr.c +++ b/sys/arch/sun3/sun3/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.14 1999/01/08 04:29:10 millert Exp $ */ +/* $OpenBSD: disksubr.c,v 1.15 2000/07/02 17:51:35 miod Exp $ */ /* $NetBSD: disksubr.c,v 1.14 1996/09/26 18:10:21 gwr Exp $ */ /* @@ -52,10 +52,12 @@ #include <sys/disk.h> #include <sys/dkbad.h> +#include <machine/cpu.h> #include <machine/sun_disklabel.h> - -/* XXX encoding of disk minor numbers, should be elsewhere... */ -#define dkpart(dev) (minor(dev) & 7) + +#if MAXPARTITIONS != 16 +#warn beware: Sun disklabel compatibility assumes MAXPARTITIONS == 16 +#endif #define b_cylin b_resid @@ -63,8 +65,9 @@ #error "Default value of LABELSECTOR no longer zero?" #endif -static char * disklabel_sun_to_bsd(char *, struct disklabel *); -static int disklabel_bsd_to_sun(struct disklabel *, char *); +static char * disklabel_sun_to_bsd __P((char *, struct disklabel *)); +static int disklabel_bsd_to_sun __P((struct disklabel *, char *)); +static __inline u_long sun_extended_sum __P((struct sun_disklabel *)); /* * Attempt to read a disk label from a device @@ -89,23 +92,27 @@ readdisklabel(dev, strat, lp, clp, spoofonly) struct buf *bp; struct disklabel *dlp; struct sun_disklabel *slp; - int error; + int error, i; - /* minimal requirements for archtypal disk label */ + /* minimal requirements for archetypal disk label */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; - lp->d_npartitions = 1; - if (lp->d_partitions[0].p_size == 0) - lp->d_partitions[0].p_size = 0x1fffffff; + lp->d_npartitions = RAW_PART + 1; + for (i = 0; i < RAW_PART; i++) { + lp->d_partitions[i].p_size = 0; + lp->d_partitions[i].p_offset = 0; + } + if (lp->d_partitions[i].p_size == 0) + lp->d_partitions[i].p_size = 0x1fffffff; lp->d_partitions[0].p_offset = 0; - /* obtain buffer to probe drive with */ - bp = geteblk((int)lp->d_secsize); - /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly) return (NULL); + /* obtain buffer to probe drive with */ + bp = geteblk((int)lp->d_secsize); + /* next, dig out disk label */ bp->b_dev = dev; bp->b_blkno = LABELSECTOR; @@ -116,7 +123,7 @@ readdisklabel(dev, strat, lp, clp, spoofonly) /* if successful, locate disk label within block and validate */ error = biowait(bp); - if (!error) { + if (error == 0) { /* Save the whole block in case it has info we need. */ bcopy(bp->b_un.b_addr, clp->cd_block, sizeof(clp->cd_block)); } @@ -127,15 +134,14 @@ readdisklabel(dev, strat, lp, clp, spoofonly) /* Check for a Sun disk label (for PROM compatibility). */ slp = (struct sun_disklabel *) clp->cd_block; - if (slp->sl_magic == SUN_DKMAGIC) { - return(disklabel_sun_to_bsd(clp->cd_block, lp)); - } + if (slp->sl_magic == SUN_DKMAGIC) + return (disklabel_sun_to_bsd(clp->cd_block, lp)); - /* Check for a OpenBSD disk label (PROM can not boot it). */ + /* 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)) - return("OpenBSD disk label corrupted"); + return("disk label corrupted"); *lp = *dlp; /* struct assignment */ return(NULL); } @@ -177,8 +183,8 @@ setdisklabel(olp, nlp, openmask, clp) dkcksum(nlp) != 0) return (EINVAL); - while (openmask != 0) { - i = ffs(openmask) - 1; + while ((i = ffs((long)openmask)) != 0) { + i--; openmask &= ~(1 << i); if (nlp->d_npartitions <= i) return (EBUSY); @@ -213,7 +219,7 @@ writedisklabel(dev, strat, lp, clp) if (error) return(error); -#if 0 /* XXX - Allow writing OpenBSD disk labels? */ +#if 0 /* XXX - Allow writing native disk labels? */ { struct disklabel *dlp; dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); @@ -251,7 +257,7 @@ bounds_check_with_label(bp, lp, osdep, wlabel) int wlabel; { #define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE)) - struct partition *p = lp->d_partitions + dkpart(bp->b_dev); + struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); int sz = howmany(bp->b_bcount, DEV_BSIZE); /* avoid division by zero */ @@ -262,7 +268,8 @@ bounds_check_with_label(bp, lp, osdep, wlabel) /* overwriting disk label ? */ /* XXX should also protect bootstrap in first 8K */ - /* XXX PR#2598: labelsect is always sector zero. */ + /* XXX this assumes everything <=LABELSECTOR is label! */ + /* But since LABELSECTOR is 0, that's ok for now. */ if (((bp->b_blkno + blockpersec(p->p_offset, lp)) <= LABELSECTOR) && ((bp->b_flags & B_READ) == 0) && (wlabel == 0)) { bp->b_error = EROFS; @@ -286,7 +293,7 @@ bounds_check_with_label(bp, lp, osdep, wlabel) } /* calculate cylinder for disksort to order transfers with */ - bp->b_cylin = (bp->b_blkno + blockpersec(p->p_offset, lp)) / + bp->b_resid = (bp->b_blkno + blockpersec(p->p_offset, lp)) / lp->d_secpercyl; return(1); @@ -318,7 +325,7 @@ dk_establish(dk, dev) /* What partition types to assume for Sun disklabels: */ static u_char -sun_fstypes[8] = { +sun_fstypes[16] = { FS_BSDFFS, /* a */ FS_SWAP, /* b */ FS_UNUSED, /* c - whole disk */ @@ -327,9 +334,38 @@ sun_fstypes[8] = { FS_BSDFFS, /* f */ FS_BSDFFS, /* g */ FS_BSDFFS, /* h */ + FS_BSDFFS, /* i */ + FS_BSDFFS, /* j */ + FS_BSDFFS, /* k */ + FS_BSDFFS, /* l */ + FS_BSDFFS, /* m */ + FS_BSDFFS, /* n */ + FS_BSDFFS, /* o */ + FS_BSDFFS /* p */ }; /* + * Given a struct sun_disklabel, assume it has an extended partition + * table and compute the correct value for sl_xpsum. + */ +static __inline u_long +sun_extended_sum(sl) + struct sun_disklabel *sl; +{ + u_long lsum; + u_long *xp; + u_long *ep; + + xp = (u_long *) &sl->sl_xpmag; + ep = (u_long *) &sl->sl_xxx1[0]; + + lsum = 0; + for (; xp < ep; xp++) + lsum += *xp; + return(lsum); +} + +/* * Given a SunOS disk label, set lp to a BSD disk label. * Returns NULL on success, else an error string. * @@ -376,7 +412,7 @@ disklabel_sun_to_bsd(cp, lp) lp->d_rpm = sl->sl_rpm; lp->d_interleave = sl->sl_interleave; - lp->d_npartitions = 8; + lp->d_npartitions = MAXPARTITIONS; /* These are as defined in <ufs/ffs/fs.h> */ lp->d_bbsize = 8192; /* XXX */ lp->d_sbsize = 8192; /* XXX */ @@ -386,18 +422,47 @@ disklabel_sun_to_bsd(cp, lp) npp = &lp->d_partitions[i]; npp->p_offset = spp->sdkp_cyloffset * secpercyl; npp->p_size = spp->sdkp_nsectors; - if (npp->p_size == 0) + if (npp->p_size == 0) { npp->p_fstype = FS_UNUSED; - else { - /* Partition has non-zero size. Set type, etc. */ + } else { npp->p_fstype = sun_fstypes[i]; - /* - * The sun label does not store the FFS fields, - * so just set them with default values here. - * XXX: This keeps newfs from trying to rewrite - * XXX: the disk label in the most common case. - * XXX: (Should remove that code from newfs...) - */ + if (npp->p_fstype == FS_BSDFFS) { + /* + * The sun label does not store the FFS fields, + * so just set them with default values here. + */ + npp->p_fsize = 1024; + npp->p_frag = 8; + npp->p_cpg = 16; + } + } + } + + /* Clear "extended" partition info, tentatively */ + for (i = 0; i < SUNXPART; i++) { + npp = &lp->d_partitions[i+8]; + npp->p_offset = 0; + npp->p_size = 0; + npp->p_fstype = FS_UNUSED; + } + + /* Check to see if there's an "extended" partition table */ + if (sl->sl_xpmag == SL_XPMAG && + sun_extended_sum(sl) == sl->sl_xpsum) { /* ...yes! */ + /* + * There is. Copy over the "extended" partitions. + * This code parallels the loop for partitions a-h. + */ + for (i = 0; i < SUNXPART; i++) { + spp = &sl->sl_xpart[i]; + npp = &lp->d_partitions[i+8]; + npp->p_offset = spp->sdkp_cyloffset * secpercyl; + npp->p_size = spp->sdkp_nsectors; + if (npp->p_size == 0) { + npp->p_fstype = FS_UNUSED; + continue; + } + npp->p_fstype = sun_fstypes[i+8]; if (npp->p_fstype == FS_BSDFFS) { npp->p_fsize = 1024; npp->p_frag = 8; @@ -408,8 +473,7 @@ disklabel_sun_to_bsd(cp, lp) lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); - - return(NULL); + return (NULL); } /* @@ -429,16 +493,17 @@ disklabel_bsd_to_sun(lp, cp) int i, secpercyl; u_short cksum, *sp1, *sp2; - if (lp->d_secsize != 512) - return (EINVAL); + /* Enforce preconditions */ + 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; - sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders; /* XXX */ sl->sl_sparespercyl = lp->d_sparespercyl; + sl->sl_pcylinders = lp->d_ncylinders + lp->d_acylinders; /* XXX */ sl->sl_interleave = lp->d_interleave; sl->sl_ncylinders = lp->d_ncylinders; sl->sl_acylinders = lp->d_acylinders; @@ -457,6 +522,40 @@ disklabel_bsd_to_sun(lp, cp) } sl->sl_magic = SUN_DKMAGIC; + /* + * The reason we store the extended table stuff only conditionally + * is so that a label that doesn't need it will have NULs there, like + * a "traditional" Sun label. Since Suns seem to ignore everything + * between sl_text and sl_rpm, this probably doesn't matter, but it + * certainly doesn't hurt anything and it's easy to do. + */ + for (i = 0; i < SUNXPART; i++) { + if (lp->d_partitions[i+8].p_offset || + lp->d_partitions[i+8].p_size) + break; + } + /* We do need to load the extended table? */ + if (i < SUNXPART) { + sl->sl_xpmag = SL_XPMAG; + for (i = 0; i < SUNXPART; i++) { + spp = &sl->sl_xpart[i]; + npp = &lp->d_partitions[i+8]; + if (npp->p_offset % secpercyl) + return (EINVAL); + sl->sl_xpart[i].sdkp_cyloffset = + npp->p_offset / secpercyl; + sl->sl_xpart[i].sdkp_nsectors = npp->p_size; + } + sl->sl_xpsum = sun_extended_sum(sl); + } else { + sl->sl_xpmag = 0; + for (i = 0; i < SUNXPART; i++) { + sl->sl_xpart[i].sdkp_cyloffset = 0; + sl->sl_xpart[i].sdkp_nsectors = 0; + } + sl->sl_xpsum = 0; + } + /* Correct the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); |