diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2011-10-25 18:34:38 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2011-10-25 18:34:38 +0000 |
commit | e313d737d1aa905b3c79a36b6348fee13623da3c (patch) | |
tree | a12ecb817ac4a461d7136b3a52a888064924a0ba /sys/arch/luna88k | |
parent | b3b1ff3b297878425f823c8cdb27ed13470078dd (diff) |
Bring luna88k disklabel handling code in sync with sparc, except for the
SunOS vs UniOS differences for the legacy part (first eight partitions), which
are preserved. Tested by aoyama@
Diffstat (limited to 'sys/arch/luna88k')
-rw-r--r-- | sys/arch/luna88k/luna88k/disksubr.c | 164 |
1 files changed, 127 insertions, 37 deletions
diff --git a/sys/arch/luna88k/luna88k/disksubr.c b/sys/arch/luna88k/luna88k/disksubr.c index 57d3b766520..6aea8c1740b 100644 --- a/sys/arch/luna88k/luna88k/disksubr.c +++ b/sys/arch/luna88k/luna88k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.51 2011/10/21 09:36:52 miod Exp $ */ +/* $OpenBSD: disksubr.c,v 1.52 2011/10/25 18:34:37 miod Exp $ */ /* $NetBSD: disksubr.c,v 1.12 2002/02/19 17:09:44 wiz Exp $ */ /* @@ -90,6 +90,7 @@ int disklabel_om_to_bsd(struct sun_disklabel *, struct disklabel *); int disklabel_bsd_to_om(struct disklabel *, struct sun_disklabel *); +static __inline u_int sun_extended_sum(struct sun_disklabel *, void *); /* * Attempt to read a disk label from a device @@ -103,6 +104,7 @@ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { + struct sun_disklabel *slp; struct buf *bp = NULL; int error; @@ -118,7 +120,6 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; bp->b_blkno = LABELSECTOR; - bp->b_cylinder = 0; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); @@ -128,9 +129,11 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), goto done; } - error = disklabel_om_to_bsd((struct sun_disklabel *)bp->b_data, lp); - if (error == 0) + slp = (struct sun_disklabel *)bp->b_data; + if (sl->sl_magic == SUN_DKMAGIC) { + error = disklabel_om_to_bsd(slp, lp); goto done; + } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); @@ -170,23 +173,13 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - /* Read the on disk label. */ - bp->b_blkno = LABELSECTOR; - bp->b_cylinder = 0; - bp->b_bcount = lp->d_secsize; - CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); - SET(bp->b_flags, B_BUSY | B_READ | B_RAW); - - (*strat)(bp); - error = biowait(bp); - if (error) - goto done; - - /* Write out the updated label. */ error = disklabel_bsd_to_om(lp, (struct sun_disklabel *)bp->b_data); if (error) goto done; + /* Write out the updated label. */ + bp->b_blkno = LABELSECTOR; + bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW); (*strat)(bp); @@ -210,18 +203,44 @@ done: /* What partition types to assume for Sun disklabels: */ static const u_char -sun_fstypes[8] = { +sun_fstypes[16] = { FS_BSDFFS, /* a */ FS_SWAP, /* b */ - FS_OTHER, /* c - whole disk */ + FS_UNUSED, /* c - whole disk */ FS_BSDFFS, /* d */ FS_BSDFFS, /* e */ 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_int +sun_extended_sum(struct sun_disklabel *sl, void *end) +{ + u_int sum, *xp, *ep; + + xp = (u_int *)&sl->sl_xpmag; + ep = (u_int *)end; + + sum = 0; + for (; xp < ep; xp++) + sum += *xp; + return (sum); +} + +/* * Given a UniOS/ISI disk label, set lp to a BSD disk label. * * The BSD label is cleared out before this is called. @@ -234,9 +253,6 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) int i, secpercyl; u_short cksum = 0, *sp1, *sp2; - if (sl->sl_magic != SUN_DKMAGIC) - return (EINVAL); - /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); @@ -245,7 +261,6 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) if (cksum != 0) return (EINVAL); /* UniOS disk label, bad checksum */ - memset((caddr_t)lp, 0, sizeof(struct disklabel)); /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; @@ -267,11 +282,6 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) lp->d_acylinders = sl->sl_acylinders; - if (sl->sl_rpm == 0) { - /* UniOS label has blkoffset, not cyloffset */ - secpercyl = 1; - } - lp->d_npartitions = MAXPARTITIONS; /* These are as defined in <ufs/ffs/fs.h> */ lp->d_bbsize = 8192; /* XXX */ @@ -280,7 +290,11 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) for (i = 0; i < 8; i++) { spp = &sl->sl_part[i]; npp = &lp->d_partitions[i]; - DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); + /* UniOS label uses blkoffset, not cyloffset */ + if (sl->sl_rpm == 0) + DL_SETPOFFSET(npp, spp->sdkp_cyloffset); + else + DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; @@ -292,7 +306,7 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) * so just set them with default values here. */ npp->p_fragblock = - DISKLABELV1_FFS_FRAGBLOCK(1024, 8); + DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } @@ -302,12 +316,61 @@ disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) * XXX BandAid XXX * UniOS rootfs sits on part c which don't begin at sect 0, * and impossible to mount. Thus, make it usable as part b. + * XXX how to setup a swap partition on disks shared with UniOS??? */ if (sl->sl_rpm == 0 && DL_GETPOFFSET(&lp->d_partitions[2]) != 0) { lp->d_partitions[1] = lp->d_partitions[2]; lp->d_partitions[1].p_fstype = FS_BSDFFS; } + /* Clear "extended" partition info, tentatively */ + for (i = 0; i < SUNXPART; i++) { + npp = &lp->d_partitions[i+8]; + DL_SETPOFFSET(npp, 0); + DL_SETPSIZE(npp, 0); + npp->p_fstype = FS_UNUSED; + } + + /* Check to see if there's an "extended" partition table + * SL_XPMAG partitions had checksums up to just before the + * (new) sl_types variable, while SL_XPMAGTYP partitions have + * checksums up to the just before the (new) sl_xxx1 variable. + */ + if ((sl->sl_xpmag == SL_XPMAG && + sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) || + (sl->sl_xpmag == SL_XPMAGTYP && + sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) { + /* + * 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]; + /* no need to be UniOS compatible here */ + DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); + DL_SETPSIZE(npp, spp->sdkp_nsectors); + if (DL_GETPSIZE(npp) == 0) { + npp->p_fstype = FS_UNUSED; + continue; + } + npp->p_fstype = sun_fstypes[i+8]; + if (npp->p_fstype == FS_BSDFFS) { + npp->p_fragblock = + DISKLABELV1_FFS_FRAGBLOCK(2048, 8); + npp->p_cpg = 16; + } + } + if (sl->sl_xpmag == SL_XPMAGTYP) { + for (i = 0; i < MAXPARTITIONS; i++) { + npp = &lp->d_partitions[i]; + npp->p_fstype = sl->sl_types[i]; + npp->p_fragblock = sl->sl_fragblock[i]; + npp->p_cpg = sl->sl_cpg[i]; + } + } + } + lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); return (checkdisklabel(lp, lp, 0, DL_GETDSIZE(lp))); @@ -323,18 +386,19 @@ disklabel_bsd_to_om(struct disklabel *lp, struct sun_disklabel *sl) { struct partition *npp; struct sun_dkpart *spp; - int i; + int i, secpercyl; u_short cksum, *sp1, *sp2; - if (lp->d_secsize != DEV_BSIZE) + if (lp->d_secsize != DEV_BSIZE || lp->d_nsectors == 0 || + lp->d_ntracks == 0) return (EINVAL); /* Format conversion. */ bzero(sl, sizeof(*sl)); memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); - sl->sl_rpm = 0; /* UniOS */ + sl->sl_rpm = 0; /* UniOS compatible */ #if 0 /* leave as was */ - sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders; /* XXX */ + sl->sl_pcylinders = lp->d_ncylinders + lp->d_acylinders; /* XXX */ #endif sl->sl_interleave = 1; sl->sl_ncylinders = lp->d_ncylinders; @@ -347,12 +411,38 @@ disklabel_bsd_to_om(struct disklabel *lp, struct sun_disklabel *sl) for (i = 0; i < 8; i++) { spp = &sl->sl_part[i]; npp = &lp->d_partitions[i]; - - spp->sdkp_cyloffset = DL_GETPOFFSET(npp); /* UniOS */ - spp->sdkp_nsectors = DL_GETPSIZE(npp); + spp->sdkp_cyloffset = 0; + spp->sdkp_nsectors = 0; + if (DL_GETPSIZE(npp)) { + spp->sdkp_cyloffset = DL_GETPOFFSET(npp); /* UniOS */ + spp->sdkp_nsectors = DL_GETPSIZE(npp); + } } sl->sl_magic = SUN_DKMAGIC; + secpercyl = sl->sl_nsectors * sl->sl_ntracks; + for (i = 0; i < SUNXPART; i++) { + spp = &sl->sl_xpart[i]; + npp = &lp->d_partitions[i+8]; + spp->sdkp_cyloffset = 0; + spp->sdkp_nsectors = 0; + if (DL_GETPSIZE(npp)) { + /* no need to be UniOS compatible here */ + if (DL_GETPOFFSET(npp) % secpercyl) + return (EINVAL); + spp->sdkp_cyloffset = DL_GETPOFFSET(npp) / secpercyl; + spp->sdkp_nsectors = DL_GETPSIZE(npp); + } + } + for (i = 0; i < MAXPARTITIONS; i++) { + npp = &lp->d_partitions[i]; + sl->sl_types[i] = npp->p_fstype; + sl->sl_fragblock[i] = npp->p_fragblock; + sl->sl_cpg[i] = npp->p_cpg; + } + sl->sl_xpmag = SL_XPMAGTYP; + sl->sl_xpsum = sun_extended_sum(sl, &sl->sl_xxx1); + /* Correct the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); |