xref: /netbsd-src/sys/dev/sun/disksubr.c (revision c20fcc6f26443cf1dd0d06fd92a9eb36b3c409cd)
1*c20fcc6fSjdc /*	$NetBSD: disksubr.c,v 1.17 2020/05/03 06:31:02 jdc Exp $ */
26fb817f5Sbouyer 
36fb817f5Sbouyer /*
46fb817f5Sbouyer  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
56fb817f5Sbouyer  * All rights reserved.
66fb817f5Sbouyer  *
76fb817f5Sbouyer  * Redistribution and use in source and binary forms, with or without
86fb817f5Sbouyer  * modification, are permitted provided that the following conditions
96fb817f5Sbouyer  * are met:
106fb817f5Sbouyer  * 1. Redistributions of source code must retain the above copyright
116fb817f5Sbouyer  *    notice, this list of conditions and the following disclaimer.
126fb817f5Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
136fb817f5Sbouyer  *    notice, this list of conditions and the following disclaimer in the
146fb817f5Sbouyer  *    documentation and/or other materials provided with the distribution.
156fb817f5Sbouyer  * 3. Neither the name of the University nor the names of its contributors
166fb817f5Sbouyer  *    may be used to endorse or promote products derived from this software
176fb817f5Sbouyer  *    without specific prior written permission.
186fb817f5Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
196fb817f5Sbouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
206fb817f5Sbouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
216fb817f5Sbouyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
226fb817f5Sbouyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
236fb817f5Sbouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
246fb817f5Sbouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
256fb817f5Sbouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
266fb817f5Sbouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
276fb817f5Sbouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
286fb817f5Sbouyer  * SUCH DAMAGE.
296fb817f5Sbouyer  */
306fb817f5Sbouyer 
316fb817f5Sbouyer /*
326fb817f5Sbouyer  * Copyright (c) 1994, 1995 Gordon W. Ross
336fb817f5Sbouyer  * Copyright (c) 1994 Theo de Raadt
346fb817f5Sbouyer  * All rights reserved.
356fb817f5Sbouyer  *
366fb817f5Sbouyer  * Redistribution and use in source and binary forms, with or without
376fb817f5Sbouyer  * modification, are permitted provided that the following conditions
386fb817f5Sbouyer  * are met:
396fb817f5Sbouyer  * 1. Redistributions of source code must retain the above copyright
406fb817f5Sbouyer  *    notice, this list of conditions and the following disclaimer.
416fb817f5Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
426fb817f5Sbouyer  *    notice, this list of conditions and the following disclaimer in the
436fb817f5Sbouyer  *    documentation and/or other materials provided with the distribution.
446fb817f5Sbouyer  *
456fb817f5Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
466fb817f5Sbouyer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
476fb817f5Sbouyer  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
486fb817f5Sbouyer  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
496fb817f5Sbouyer  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
506fb817f5Sbouyer  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
516fb817f5Sbouyer  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
526fb817f5Sbouyer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
536fb817f5Sbouyer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
546fb817f5Sbouyer  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
556fb817f5Sbouyer  */
566fb817f5Sbouyer 
576fb817f5Sbouyer #include <sys/cdefs.h>
58*c20fcc6fSjdc __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.17 2020/05/03 06:31:02 jdc Exp $");
596fb817f5Sbouyer 
606fb817f5Sbouyer #include <sys/param.h>
616fb817f5Sbouyer #include <sys/systm.h>
626fb817f5Sbouyer #include <sys/buf.h>
636fb817f5Sbouyer #include <sys/ioccom.h>
646fb817f5Sbouyer #include <sys/device.h>
656fb817f5Sbouyer #include <sys/disklabel.h>
666fb817f5Sbouyer #include <sys/disk.h>
676fb817f5Sbouyer #include <sys/dkbad.h>
686fb817f5Sbouyer 
696fb817f5Sbouyer #include <dev/sun/disklabel.h>
706fb817f5Sbouyer 
716fb817f5Sbouyer #if LABELSECTOR != 0
726fb817f5Sbouyer #error  "Default value of LABELSECTOR no longer zero?"
736fb817f5Sbouyer #endif
746fb817f5Sbouyer 
75309409f7Schristos static	const char *disklabel_sun_to_bsd(char *, struct disklabel *);
7618db93c7Sperry static	int disklabel_bsd_to_sun(struct disklabel *, char *);
776fb817f5Sbouyer 
786fb817f5Sbouyer /*
796fb817f5Sbouyer  * Attempt to read a disk label from a device
806fb817f5Sbouyer  * using the indicated strategy routine.
816fb817f5Sbouyer  * The label must be partly set up before this:
826fb817f5Sbouyer  * secpercyl, secsize and anything required for a block i/o read
836fb817f5Sbouyer  * operation in the driver's strategy/start routines
846fb817f5Sbouyer  * must be filled in before calling us.
856fb817f5Sbouyer  *
866fb817f5Sbouyer  * Return buffer for use in signalling errors if requested.
876fb817f5Sbouyer  *
886fb817f5Sbouyer  * Returns null on success and an error string on failure.
896fb817f5Sbouyer  */
906fb817f5Sbouyer const char *
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)917cc9af7dSdsl readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp)
926fb817f5Sbouyer {
936fb817f5Sbouyer 	struct buf *bp;
946fb817f5Sbouyer 	struct disklabel *dlp;
956fb817f5Sbouyer 	struct sun_disklabel *slp;
966fb817f5Sbouyer 	int error;
976fb817f5Sbouyer 
986fb817f5Sbouyer 	/* minimal requirements for archtypal disk label */
996fb817f5Sbouyer 	if (lp->d_secperunit == 0)
1006fb817f5Sbouyer 		lp->d_secperunit = 0x1fffffff;
1016fb817f5Sbouyer 	if (lp->d_npartitions == 0) {
1026fb817f5Sbouyer 		lp->d_npartitions = RAW_PART + 1;
1036fb817f5Sbouyer 		if (lp->d_partitions[RAW_PART].p_size == 0)
1046fb817f5Sbouyer 			lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
1056fb817f5Sbouyer 		lp->d_partitions[RAW_PART].p_offset = 0;
1066fb817f5Sbouyer 	}
107*c20fcc6fSjdc 	if (lp->d_secsize == 0)
108*c20fcc6fSjdc 		return ("sector size 0");
1096fb817f5Sbouyer 
1106fb817f5Sbouyer 	/* obtain buffer to probe drive with */
1116fb817f5Sbouyer 	bp = geteblk((int)lp->d_secsize);
1126fb817f5Sbouyer 
1136fb817f5Sbouyer 	/* next, dig out disk label */
1146fb817f5Sbouyer 	bp->b_dev = dev;
1156fb817f5Sbouyer 	bp->b_blkno = LABELSECTOR;
1166fb817f5Sbouyer 	bp->b_cylinder = 0;
1176fb817f5Sbouyer 	bp->b_bcount = lp->d_secsize;
1186fb817f5Sbouyer 	bp->b_flags |= B_READ;
1196fb817f5Sbouyer 	(*strat)(bp);
1206fb817f5Sbouyer 
1216fb817f5Sbouyer 	/* if successful, locate disk label within block and validate */
1226fb817f5Sbouyer 	error = biowait(bp);
1236fb817f5Sbouyer 	if (error == 0) {
1246fb817f5Sbouyer 		/* Save the whole block in case it has info we need. */
1256fb817f5Sbouyer 		memcpy(clp->cd_block, bp->b_data, sizeof(clp->cd_block));
1266fb817f5Sbouyer 	}
127c97e9c4eSad 	brelse(bp, 0);
1286fb817f5Sbouyer 	if (error)
1296fb817f5Sbouyer 		return ("disk label read error");
1306fb817f5Sbouyer 
1316fb817f5Sbouyer 	/* Check for a NetBSD disk label at LABELOFFSET */
1326fb817f5Sbouyer 	dlp = (struct disklabel *) (clp->cd_block + LABELOFFSET);
1336fb817f5Sbouyer 	if (dlp->d_magic == DISKMAGIC) {
1346fb817f5Sbouyer 		if (dkcksum(dlp))
1356fb817f5Sbouyer 			return ("NetBSD disk label corrupted");
1366fb817f5Sbouyer 		*lp = *dlp;
1376fb817f5Sbouyer 		return (NULL);
1386fb817f5Sbouyer 	}
1396fb817f5Sbouyer 
1406fb817f5Sbouyer 	/* Check for a Sun disk label (for PROM compatibility). */
1416fb817f5Sbouyer 	slp = (struct sun_disklabel *) clp->cd_block;
1426fb817f5Sbouyer 	if (slp->sl_magic == SUN_DKMAGIC)
1436fb817f5Sbouyer 		return (disklabel_sun_to_bsd(clp->cd_block, lp));
1446fb817f5Sbouyer 
1456fb817f5Sbouyer 	/*
1466fb817f5Sbouyer 	 * Check for a NetBSD disk label somewhere in LABELSECTOR
1476fb817f5Sbouyer 	 * (compat with others big-endian boxes)
1486fb817f5Sbouyer 	 */
1496fb817f5Sbouyer 	for (dlp = (struct disklabel *)clp->cd_block;
1506fb817f5Sbouyer 	    dlp <= (struct disklabel *)((char *)clp->cd_block +
1516fb817f5Sbouyer 	    DEV_BSIZE - sizeof(*dlp));
1526fb817f5Sbouyer 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
1536fb817f5Sbouyer 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
1546fb817f5Sbouyer 			continue;
1556fb817f5Sbouyer 		}
1566fb817f5Sbouyer 		if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0)
1576fb817f5Sbouyer 			return("NetBSD disk label corrupted");
1586fb817f5Sbouyer 		else {
1596fb817f5Sbouyer 			*lp = *dlp;
1606fb817f5Sbouyer 			return(NULL);
1616fb817f5Sbouyer 		}
1626fb817f5Sbouyer 	}
1636fb817f5Sbouyer 
1646fb817f5Sbouyer 	memset(clp->cd_block, 0, sizeof(clp->cd_block));
165b9dbf5baSmartin 	return NULL;
1666fb817f5Sbouyer }
1676fb817f5Sbouyer 
1686fb817f5Sbouyer /*
1696fb817f5Sbouyer  * Write disk label back to device after modification.
1706fb817f5Sbouyer  * Current label is already in clp->cd_block[]
1716fb817f5Sbouyer  */
1726fb817f5Sbouyer int
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)1737cc9af7dSdsl writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp)
1746fb817f5Sbouyer {
1756fb817f5Sbouyer 	struct buf *bp;
1766fb817f5Sbouyer 	int error;
1776fb817f5Sbouyer 	struct disklabel *dlp;
1786fb817f5Sbouyer 	struct sun_disklabel *slp;
1796fb817f5Sbouyer 
1806fb817f5Sbouyer 	/*
1816fb817f5Sbouyer 	 * Embed native label in a piece of wasteland.
1826fb817f5Sbouyer 	 */
1836fb817f5Sbouyer 	if (sizeof(struct disklabel) > sizeof slp->sl_bsdlabel)
1846fb817f5Sbouyer 		return EFBIG;
1856fb817f5Sbouyer 
1866fb817f5Sbouyer 	slp = (struct sun_disklabel *)clp->cd_block;
1876fb817f5Sbouyer 	memset(slp->sl_bsdlabel, 0, sizeof(slp->sl_bsdlabel));
1886fb817f5Sbouyer 	dlp = (struct disklabel *)slp->sl_bsdlabel;
1896fb817f5Sbouyer 	*dlp = *lp;
1906fb817f5Sbouyer 
1916fb817f5Sbouyer 	/* Build a SunOS compatible label around the native label */
1926fb817f5Sbouyer 	error = disklabel_bsd_to_sun(lp, clp->cd_block);
1936fb817f5Sbouyer 	if (error)
1946fb817f5Sbouyer 		return (error);
1956fb817f5Sbouyer 
1966fb817f5Sbouyer 	/* Get a buffer and copy the new label into it. */
1976fb817f5Sbouyer 	bp = geteblk((int)lp->d_secsize);
1986fb817f5Sbouyer 	memcpy(bp->b_data, clp->cd_block, sizeof(clp->cd_block));
1996fb817f5Sbouyer 
2006fb817f5Sbouyer 	/* Write out the updated label. */
2016fb817f5Sbouyer 	bp->b_dev = dev;
2026fb817f5Sbouyer 	bp->b_blkno = LABELSECTOR;
2036fb817f5Sbouyer 	bp->b_cylinder = 0;
2046fb817f5Sbouyer 	bp->b_bcount = lp->d_secsize;
2056fb817f5Sbouyer 	bp->b_flags |= B_WRITE;
2066fb817f5Sbouyer 	(*strat)(bp);
2076fb817f5Sbouyer 	error = biowait(bp);
208c97e9c4eSad 	brelse(bp, 0);
2096fb817f5Sbouyer 
2106fb817f5Sbouyer 	return (error);
2116fb817f5Sbouyer }
2126fb817f5Sbouyer 
2136fb817f5Sbouyer /************************************************************************
2146fb817f5Sbouyer  *
2156fb817f5Sbouyer  * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
2166fb817f5Sbouyer  * and then substantially rewritten by Gordon W. Ross
2176fb817f5Sbouyer  *
2186fb817f5Sbouyer  ************************************************************************/
2196fb817f5Sbouyer 
2206fb817f5Sbouyer /* What partition types to assume for Sun disklabels: */
2216fb817f5Sbouyer static u_char
2226fb817f5Sbouyer sun_fstypes[8] = {
2236fb817f5Sbouyer 	FS_BSDFFS,	/* a */
2246fb817f5Sbouyer 	FS_SWAP,	/* b */
2256fb817f5Sbouyer 	FS_OTHER,	/* c - whole disk */
2266fb817f5Sbouyer 	FS_BSDFFS,	/* d */
2276fb817f5Sbouyer 	FS_BSDFFS,	/* e */
2286fb817f5Sbouyer 	FS_BSDFFS,	/* f */
2296fb817f5Sbouyer 	FS_BSDFFS,	/* g */
2306fb817f5Sbouyer 	FS_BSDFFS,	/* h */
2316fb817f5Sbouyer };
2326fb817f5Sbouyer 
2336fb817f5Sbouyer /*
2346fb817f5Sbouyer  * Given a SunOS disk label, set lp to a BSD disk label.
2356fb817f5Sbouyer  * Returns NULL on success, else an error string.
2366fb817f5Sbouyer  *
2376fb817f5Sbouyer  * The BSD label is cleared out before this is called.
2386fb817f5Sbouyer  */
239f1faf374Schristos static const char *
disklabel_sun_to_bsd(char * cp,struct disklabel * lp)240454af1c0Sdsl disklabel_sun_to_bsd(char *cp, struct disklabel *lp)
2416fb817f5Sbouyer {
2426fb817f5Sbouyer 	struct sun_disklabel *sl;
2436fb817f5Sbouyer 	struct partition *npp;
2446fb817f5Sbouyer 	struct sun_dkpart *spp;
2456fb817f5Sbouyer 	int i, secpercyl;
246d6bdba58Smartin 	unsigned int secpblck;
2476fb817f5Sbouyer 	u_short cksum, *sp1, *sp2;
2486fb817f5Sbouyer 
2496fb817f5Sbouyer 	sl = (struct sun_disklabel *)cp;
2506fb817f5Sbouyer 
2516fb817f5Sbouyer 	/* Verify the XOR check. */
2526fb817f5Sbouyer 	sp1 = (u_short *)sl;
2536fb817f5Sbouyer 	sp2 = (u_short *)(sl + 1);
2546fb817f5Sbouyer 	cksum = 0;
2556fb817f5Sbouyer 	while (sp1 < sp2)
2566fb817f5Sbouyer 		cksum ^= *sp1++;
2576fb817f5Sbouyer 	if (cksum != 0)
2586fb817f5Sbouyer 		return("SunOS disk label, bad checksum");
2596fb817f5Sbouyer 
2606fb817f5Sbouyer 	/* Format conversion. */
2616fb817f5Sbouyer 	lp->d_magic = DISKMAGIC;
2626fb817f5Sbouyer 	lp->d_magic2 = DISKMAGIC;
2636fb817f5Sbouyer 	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
2646fb817f5Sbouyer 
265d6bdba58Smartin 	secpblck = lp->d_secsize / 512;
266d6bdba58Smartin 	if (secpblck == 0) secpblck = 1; /* can't happen */
2676fb817f5Sbouyer 	lp->d_secsize = 512;
2686fb817f5Sbouyer 	lp->d_nsectors   = sl->sl_nsectors;
2696fb817f5Sbouyer 	lp->d_ntracks    = sl->sl_ntracks;
2706fb817f5Sbouyer 	lp->d_ncylinders = sl->sl_ncylinders;
2716fb817f5Sbouyer 
2726fb817f5Sbouyer 	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
2736fb817f5Sbouyer 	lp->d_secpercyl  = secpercyl;
2746fb817f5Sbouyer 	lp->d_secperunit = secpercyl * sl->sl_ncylinders;
2756fb817f5Sbouyer 
2766fb817f5Sbouyer 	lp->d_sparespercyl = sl->sl_sparespercyl;
2776fb817f5Sbouyer 	lp->d_acylinders   = sl->sl_acylinders;
2786fb817f5Sbouyer 	lp->d_rpm          = sl->sl_rpm;
2796fb817f5Sbouyer 	lp->d_interleave   = sl->sl_interleave;
2806fb817f5Sbouyer 
2816fb817f5Sbouyer 	lp->d_npartitions = 8;
2826fb817f5Sbouyer 	/* These are as defined in <ufs/ffs/fs.h> */
2836fb817f5Sbouyer 	lp->d_bbsize = 8192;	/* XXX */
2846fb817f5Sbouyer 	lp->d_sbsize = 8192;	/* XXX */
2856fb817f5Sbouyer 
2866fb817f5Sbouyer 	for (i = 0; i < 8; i++) {
2876fb817f5Sbouyer 		spp = &sl->sl_part[i];
2886fb817f5Sbouyer 		npp = &lp->d_partitions[i];
289d6bdba58Smartin 
290238cb98aSmartin 		if (npp->p_fstype == FS_ISO9660
291d6bdba58Smartin 		    && spp->sdkp_cyloffset * secpercyl == npp->p_offset*secpblck
292d6bdba58Smartin 		    && spp->sdkp_nsectors <= npp->p_size*secpblck
293238cb98aSmartin 		    && npp->p_size > 0 && spp->sdkp_nsectors > 0) {
294238cb98aSmartin 			/*
295238cb98aSmartin 			 * This happens for example on sunlabel'd hybrid
296238cb98aSmartin 			 * (ffs + ISO9660) CDs, like our install CDs.
297238cb98aSmartin 			 * The cd driver has initialized a valid ISO9660
298238cb98aSmartin 			 * partition (including session parameters), so
299238cb98aSmartin 			 * we better not overwrite it.
300238cb98aSmartin 			 */
301d6bdba58Smartin 			npp->p_offset *= secpblck;
302d6bdba58Smartin 			npp->p_size = spp->sdkp_nsectors;
303d6bdba58Smartin 			npp->p_cdsession *= secpblck;
304238cb98aSmartin 			continue;
305238cb98aSmartin 		}
3066fb817f5Sbouyer 		npp->p_offset = spp->sdkp_cyloffset * secpercyl;
3076fb817f5Sbouyer 		npp->p_size = spp->sdkp_nsectors;
3086fb817f5Sbouyer 		if (npp->p_size == 0) {
3096fb817f5Sbouyer 			npp->p_fstype = FS_UNUSED;
3106fb817f5Sbouyer 		} else {
3116fb817f5Sbouyer 			npp->p_fstype = sun_fstypes[i];
3126fb817f5Sbouyer 			if (npp->p_fstype == FS_BSDFFS) {
3136fb817f5Sbouyer 				/*
3146fb817f5Sbouyer 				 * The sun label does not store the FFS fields,
3156fb817f5Sbouyer 				 * so just set them with default values here.
3166fb817f5Sbouyer 				 */
3176fb817f5Sbouyer 				npp->p_fsize = 1024;
3186fb817f5Sbouyer 				npp->p_frag = 8;
3196fb817f5Sbouyer 				npp->p_cpg = 16;
3206fb817f5Sbouyer 			}
3216fb817f5Sbouyer 		}
3226fb817f5Sbouyer 	}
3236fb817f5Sbouyer 
3246fb817f5Sbouyer 	lp->d_checksum = 0;
3256fb817f5Sbouyer 	lp->d_checksum = dkcksum(lp);
3266fb817f5Sbouyer 	return (NULL);
3276fb817f5Sbouyer }
3286fb817f5Sbouyer 
3296fb817f5Sbouyer /*
3306fb817f5Sbouyer  * Given a BSD disk label, update the Sun disklabel
3316fb817f5Sbouyer  * pointed to by cp with the new info.  Note that the
3326fb817f5Sbouyer  * Sun disklabel may have other info we need to keep.
3336fb817f5Sbouyer  * Returns zero or error code.
3346fb817f5Sbouyer  */
3356fb817f5Sbouyer static int
disklabel_bsd_to_sun(struct disklabel * lp,char * cp)336454af1c0Sdsl disklabel_bsd_to_sun(struct disklabel *lp, char *cp)
3376fb817f5Sbouyer {
3386fb817f5Sbouyer 	struct sun_disklabel *sl;
3396fb817f5Sbouyer 	struct partition *npp;
3406fb817f5Sbouyer 	struct sun_dkpart *spp;
3416fb817f5Sbouyer 	int i, secpercyl;
3426fb817f5Sbouyer 	u_short cksum, *sp1, *sp2;
3436fb817f5Sbouyer 
3446fb817f5Sbouyer 	if (lp->d_secsize != 512)
3456fb817f5Sbouyer 		return (EINVAL);
3466fb817f5Sbouyer 
3476fb817f5Sbouyer 	sl = (struct sun_disklabel *)cp;
3486fb817f5Sbouyer 
3496fb817f5Sbouyer 	/*
3506fb817f5Sbouyer 	 * Format conversion.
3516fb817f5Sbouyer 	 */
3526fb817f5Sbouyer 	memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
3536fb817f5Sbouyer 	sl->sl_rpm = lp->d_rpm;
3546fb817f5Sbouyer 	sl->sl_pcylinders   = lp->d_ncylinders + lp->d_acylinders; /* XXX */
3556fb817f5Sbouyer 	sl->sl_sparespercyl = lp->d_sparespercyl;
3566fb817f5Sbouyer 	sl->sl_interleave   = lp->d_interleave;
3576fb817f5Sbouyer 	sl->sl_ncylinders   = lp->d_ncylinders;
3586fb817f5Sbouyer 	sl->sl_acylinders   = lp->d_acylinders;
3596fb817f5Sbouyer 	sl->sl_ntracks      = lp->d_ntracks;
3606fb817f5Sbouyer 	sl->sl_nsectors     = lp->d_nsectors;
3616fb817f5Sbouyer 
3626fb817f5Sbouyer 	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
3636fb817f5Sbouyer 	for (i = 0; i < 8; i++) {
3646fb817f5Sbouyer 		spp = &sl->sl_part[i];
3656fb817f5Sbouyer 		npp = &lp->d_partitions[i];
3666fb817f5Sbouyer 
3676fb817f5Sbouyer 		/*
3686fb817f5Sbouyer 		 * SunOS partitions must start on a cylinder boundary.
3696fb817f5Sbouyer 		 * Note this restriction is forced upon NetBSD/sparc
3706fb817f5Sbouyer 		 * labels too, since we want to keep both labels
3716fb817f5Sbouyer 		 * synchronised.
3726fb817f5Sbouyer 		 */
3736fb817f5Sbouyer 		if (npp->p_offset % secpercyl)
3746fb817f5Sbouyer 			return (EINVAL);
3756fb817f5Sbouyer 		spp->sdkp_cyloffset = npp->p_offset / secpercyl;
3766fb817f5Sbouyer 		spp->sdkp_nsectors = npp->p_size;
3776fb817f5Sbouyer 	}
3786fb817f5Sbouyer 	sl->sl_magic = SUN_DKMAGIC;
3796fb817f5Sbouyer 
3806fb817f5Sbouyer 	/* Compute the XOR check. */
3816fb817f5Sbouyer 	sp1 = (u_short *)sl;
3826fb817f5Sbouyer 	sp2 = (u_short *)(sl + 1);
3836fb817f5Sbouyer 	sl->sl_cksum = cksum = 0;
3846fb817f5Sbouyer 	while (sp1 < sp2)
3856fb817f5Sbouyer 		cksum ^= *sp1++;
3866fb817f5Sbouyer 	sl->sl_cksum = cksum;
3876fb817f5Sbouyer 
3886fb817f5Sbouyer 	return (0);
3896fb817f5Sbouyer }
3906fb817f5Sbouyer 
3916fb817f5Sbouyer /*
3926fb817f5Sbouyer  * Search the bad sector table looking for the specified sector.
3936fb817f5Sbouyer  * Return index if found.
3946fb817f5Sbouyer  * Return -1 if not found.
3956fb817f5Sbouyer  */
3966fb817f5Sbouyer int
isbad(struct dkbad * bt,int cyl,int trk,int sec)39782357f6dSdsl isbad(struct dkbad *bt, int cyl, int trk, int sec)
3986fb817f5Sbouyer {
3996fb817f5Sbouyer 	int i;
4006fb817f5Sbouyer 	long blk, bblk;
4016fb817f5Sbouyer 
4026fb817f5Sbouyer 	blk = ((long)cyl << 16) + (trk << 8) + sec;
4036fb817f5Sbouyer 	for (i = 0; i < 126; i++) {
4046fb817f5Sbouyer 		bblk = ((long)bt->bt_bad[i].bt_cyl << 16) +
4056fb817f5Sbouyer 			bt->bt_bad[i].bt_trksec;
4066fb817f5Sbouyer 		if (blk == bblk)
4076fb817f5Sbouyer 			return (i);
4086fb817f5Sbouyer 		if (blk < bblk || bblk < 0)
4096fb817f5Sbouyer 			break;
4106fb817f5Sbouyer 	}
4116fb817f5Sbouyer 	return (-1);
4126fb817f5Sbouyer }
413