Annotation of sys/arch/luna88k/luna88k/disksubr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: disksubr.c,v 1.33 2007/06/20 18:15:45 deraadt Exp $ */
! 2: /* $NetBSD: disksubr.c,v 1.12 2002/02/19 17:09:44 wiz Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994, 1995 Gordon W. Ross
! 6: * Copyright (c) 1994 Theo de Raadt
! 7: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
! 8: * All rights reserved.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed by the University of
! 21: * California, Berkeley and its contributors.
! 22: * 4. Neither the name of the University nor the names of its contributors
! 23: * may be used to endorse or promote products derived from this software
! 24: * without specific prior written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 36: * SUCH DAMAGE.
! 37: */
! 38:
! 39: #include <sys/param.h>
! 40: #include <sys/systm.h>
! 41: #include <sys/buf.h>
! 42: #include <sys/device.h>
! 43: #include <sys/disklabel.h>
! 44: #include <sys/disk.h>
! 45:
! 46: #include <dev/sun/disklabel.h>
! 47:
! 48: /*
! 49: * UniOS disklabel (== ISI disklabel) is very similar to SunOS.
! 50: * SunOS UniOS/ISI
! 51: * text 128 128
! 52: * (pad) 292 294
! 53: * rpm 2 -
! 54: * pcyl 2 badchk 2
! 55: * sparecyl 2 maxblk 4
! 56: * (pad) 4 dtype 2
! 57: * interleave 2 ndisk 2
! 58: * ncyl 2 2
! 59: * acyl 2 2
! 60: * ntrack 2 2
! 61: * nsect 2 2
! 62: * (pad) 4 bhead 2
! 63: * - ppart 2
! 64: * dkpart[8] 64 64
! 65: * magic 2 2
! 66: * cksum 2 2
! 67: *
! 68: * Magic number value and checksum calculation are identical. Subtle
! 69: * difference is partition start address; UniOS/ISI maintains sector
! 70: * numbers while SunOS label has cylinder number.
! 71: *
! 72: * It is found that LUNA Mach2.5 has BSD label embedded at offset 64
! 73: * retaining UniOS/ISI label at the end of label block. LUNA Mach
! 74: * manipulates BSD disklabel in the same manner as 4.4BSD. It's
! 75: * uncertain LUNA Mach can create a disklabel on fresh disks since
! 76: * Mach writedisklabel logic seems to fail when no BSD label is found.
! 77: *
! 78: * Kernel handles disklabel in this way;
! 79: * - searchs BSD label at offset 64
! 80: * - if not found, searchs UniOS/ISI label at the end of block
! 81: * - kernel can distinguish whether it was SunOS label or UniOS/ISI
! 82: * label and understand both
! 83: * - kernel writes UniOS/ISI label combined with BSD label to update
! 84: * the label block
! 85: */
! 86:
! 87: #if LABELSECTOR != 0
! 88: #error "Default value of LABELSECTOR no longer zero?"
! 89: #endif
! 90:
! 91: char *disklabel_om_to_bsd(struct sun_disklabel *, struct disklabel *);
! 92: int disklabel_bsd_to_om(struct disklabel *, struct sun_disklabel *);
! 93:
! 94: /*
! 95: * Attempt to read a disk label from a device
! 96: * using the indicated strategy routine.
! 97: * The label must be partly set up before this:
! 98: * secpercyl, secsize and anything required for a block i/o read
! 99: * operation in the driver's strategy/start routines
! 100: * must be filled in before calling us.
! 101: *
! 102: * Return buffer for use in signalling errors if requested.
! 103: *
! 104: * Returns null on success and an error string on failure.
! 105: */
! 106: char *
! 107: readdisklabel(dev_t dev, void (*strat)(struct buf *),
! 108: struct disklabel *lp, int spoofonly)
! 109: {
! 110: struct sun_disklabel *slp;
! 111: struct buf *bp = NULL;
! 112: char *msg;
! 113:
! 114: if ((msg = initdisklabel(lp)))
! 115: goto done;
! 116:
! 117: /* get a buffer and initialize it */
! 118: bp = geteblk((int)lp->d_secsize);
! 119: bp->b_dev = dev;
! 120:
! 121: if (spoofonly)
! 122: goto done;
! 123:
! 124: bp->b_blkno = LABELSECTOR;
! 125: bp->b_cylinder = 0;
! 126: bp->b_bcount = lp->d_secsize;
! 127: bp->b_flags = B_BUSY | B_READ;
! 128: (*strat)(bp);
! 129: if (biowait(bp)) {
! 130: msg = "disk label read error";
! 131: goto done;
! 132: }
! 133:
! 134: slp = (struct sun_disklabel *)bp->b_data;
! 135: if (slp->sl_magic == SUN_DKMAGIC) {
! 136: msg = disklabel_om_to_bsd(slp, lp);
! 137: goto done;
! 138: }
! 139:
! 140: msg = checkdisklabel(bp->b_data + LABELOFFSET, lp);
! 141: if (msg == NULL)
! 142: goto done;
! 143:
! 144: #if defined(CD9660)
! 145: if (iso_disklabelspoof(dev, strat, lp) == 0) {
! 146: msg = NULL;
! 147: goto done;
! 148: }
! 149: #endif
! 150: #if defined(UDF)
! 151: if (udf_disklabelspoof(dev, strat, lp) == 0) {
! 152: msg = NULL;
! 153: goto done;
! 154: }
! 155: #endif
! 156:
! 157: done:
! 158: if (bp) {
! 159: bp->b_flags |= B_INVAL;
! 160: brelse(bp);
! 161: }
! 162: return (msg);
! 163: }
! 164:
! 165: /*
! 166: * Write disk label back to device after modification.
! 167: */
! 168: int
! 169: writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
! 170: {
! 171: struct buf *bp = NULL;
! 172: int error;
! 173:
! 174: /* get a buffer and initialize it */
! 175: bp = geteblk((int)lp->d_secsize);
! 176: bp->b_dev = dev;
! 177:
! 178: /* Read the on disk label. */
! 179: bp->b_blkno = LABELSECTOR;
! 180: bp->b_cylinder = 0;
! 181: bp->b_bcount = lp->d_secsize;
! 182: bp->b_flags = B_BUSY | B_READ;
! 183:
! 184: (*strat)(bp);
! 185: error = biowait(bp);
! 186: if (error)
! 187: goto done;
! 188:
! 189: /* Write out the updated label. */
! 190: error = disklabel_bsd_to_om(lp, (struct sun_disklabel *)bp->b_data);
! 191: if (error)
! 192: goto done;
! 193:
! 194: bp->b_flags = B_BUSY | B_WRITE;
! 195: (*strat)(bp);
! 196: error = biowait(bp);
! 197:
! 198: done:
! 199: if (bp) {
! 200: bp->b_flags |= B_INVAL;
! 201: brelse(bp);
! 202: }
! 203: return (error);
! 204: }
! 205:
! 206: /************************************************************************
! 207: *
! 208: * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
! 209: * and then substantially rewritten by Gordon W. Ross
! 210: *
! 211: ************************************************************************/
! 212:
! 213: /* What partition types to assume for Sun disklabels: */
! 214: static const u_char
! 215: sun_fstypes[8] = {
! 216: FS_BSDFFS, /* a */
! 217: FS_SWAP, /* b */
! 218: FS_OTHER, /* c - whole disk */
! 219: FS_BSDFFS, /* d */
! 220: FS_BSDFFS, /* e */
! 221: FS_BSDFFS, /* f */
! 222: FS_BSDFFS, /* g */
! 223: FS_BSDFFS, /* h */
! 224: };
! 225:
! 226: /*
! 227: * Given a UniOS/ISI disk label, set lp to a BSD disk label.
! 228: * Returns NULL on success, else an error string.
! 229: *
! 230: * The BSD label is cleared out before this is called.
! 231: */
! 232: char *
! 233: disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
! 234: {
! 235: struct partition *npp;
! 236: struct sun_dkpart *spp;
! 237: int i, secpercyl;
! 238: u_short cksum = 0, *sp1, *sp2;
! 239:
! 240: /* Verify the XOR check. */
! 241: sp1 = (u_short *)sl;
! 242: sp2 = (u_short *)(sl + 1);
! 243: while (sp1 < sp2)
! 244: cksum ^= *sp1++;
! 245: if (cksum != 0)
! 246: return ("UniOS disk label, bad checksum");
! 247:
! 248: memset((caddr_t)lp, 0, sizeof(struct disklabel));
! 249: /* Format conversion. */
! 250: lp->d_magic = DISKMAGIC;
! 251: lp->d_magic2 = DISKMAGIC;
! 252: lp->d_flags = D_VENDOR;
! 253: memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
! 254:
! 255: lp->d_secsize = 512;
! 256: lp->d_nsectors = sl->sl_nsectors;
! 257: lp->d_ntracks = sl->sl_ntracks;
! 258: lp->d_ncylinders = sl->sl_ncylinders;
! 259:
! 260: secpercyl = sl->sl_nsectors * sl->sl_ntracks;
! 261: lp->d_secpercyl = secpercyl;
! 262: if (DL_GETDSIZE(lp) == 0)
! 263: DL_SETDSIZE(lp, (daddr64_t)secpercyl * sl->sl_ncylinders);
! 264: lp->d_version = 1;
! 265:
! 266: lp->d_sparespercyl = 0; /* no way to know */
! 267: lp->d_acylinders = sl->sl_acylinders;
! 268: lp->d_rpm = sl->sl_rpm; /* UniOS - (empty) */
! 269: lp->d_interleave = sl->sl_interleave; /* UniOS - ndisk */
! 270:
! 271: if (sl->sl_rpm == 0) {
! 272: /* UniOS label has blkoffset, not cyloffset */
! 273: secpercyl = 1;
! 274: }
! 275:
! 276: lp->d_npartitions = 8;
! 277: /* These are as defined in <ufs/ffs/fs.h> */
! 278: lp->d_bbsize = 8192; /* XXX */
! 279: lp->d_sbsize = 8192; /* XXX */
! 280:
! 281: for (i = 0; i < 8; i++) {
! 282: spp = &sl->sl_part[i];
! 283: npp = &lp->d_partitions[i];
! 284: DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
! 285: DL_SETPSIZE(npp, spp->sdkp_nsectors);
! 286: if (DL_GETPSIZE(npp) == 0) {
! 287: npp->p_fstype = FS_UNUSED;
! 288: } else {
! 289: npp->p_fstype = sun_fstypes[i];
! 290: if (npp->p_fstype == FS_BSDFFS) {
! 291: /*
! 292: * The sun label does not store the FFS fields,
! 293: * so just set them with default values here.
! 294: */
! 295: npp->p_fragblock =
! 296: DISKLABELV1_FFS_FRAGBLOCK(1024, 8);
! 297: npp->p_cpg = 16;
! 298: }
! 299: }
! 300: }
! 301:
! 302: /*
! 303: * XXX BandAid XXX
! 304: * UniOS rootfs sits on part c which don't begin at sect 0,
! 305: * and impossible to mount. Thus, make it usable as part b.
! 306: */
! 307: if (sl->sl_rpm == 0 && DL_GETPOFFSET(&lp->d_partitions[2]) != 0) {
! 308: lp->d_partitions[1] = lp->d_partitions[2];
! 309: lp->d_partitions[1].p_fstype = FS_BSDFFS;
! 310: }
! 311:
! 312: lp->d_checksum = 0;
! 313: lp->d_checksum = dkcksum(lp);
! 314: return (NULL);
! 315: }
! 316:
! 317: /*
! 318: * Given a BSD disk label, update the UniOS disklabel
! 319: * pointed to by sl with the new info. Note that the
! 320: * UniOS disklabel may have other info we need to keep.
! 321: * Returns zero or error code.
! 322: */
! 323: int
! 324: disklabel_bsd_to_om(struct disklabel *lp, struct sun_disklabel *sl)
! 325: {
! 326: struct partition *npp;
! 327: struct sun_dkpart *spp;
! 328: int i;
! 329: u_short cksum, *sp1, *sp2;
! 330:
! 331: if (lp->d_secsize != 512)
! 332: return (EINVAL);
! 333:
! 334: /* Format conversion. */
! 335: memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
! 336: sl->sl_rpm = 0; /* UniOS */
! 337: #if 0 /* leave as was */
! 338: sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders; /* XXX */
! 339: sl->sl_sparespercyl = lp->d_sparespercyl;
! 340: #endif
! 341: sl->sl_interleave = lp->d_interleave;
! 342: sl->sl_ncylinders = lp->d_ncylinders;
! 343: sl->sl_acylinders = lp->d_acylinders;
! 344: sl->sl_ntracks = lp->d_ntracks;
! 345: sl->sl_nsectors = lp->d_nsectors;
! 346:
! 347: for (i = 0; i < 8; i++) {
! 348: spp = &sl->sl_part[i];
! 349: npp = &lp->d_partitions[i];
! 350:
! 351: spp->sdkp_cyloffset = DL_GETPOFFSET(npp); /* UniOS */
! 352: spp->sdkp_nsectors = DL_GETPSIZE(npp);
! 353: }
! 354: sl->sl_magic = SUN_DKMAGIC;
! 355:
! 356: /* Correct the XOR check. */
! 357: sp1 = (u_short *)sl;
! 358: sp2 = (u_short *)(sl + 1);
! 359: sl->sl_cksum = cksum = 0;
! 360: while (sp1 < sp2)
! 361: cksum ^= *sp1++;
! 362: sl->sl_cksum = cksum;
! 363:
! 364: return (0);
! 365: }
CVSweb