xref: /openbsd-src/sys/arch/sparc64/sparc64/disksubr.c (revision 6db064f3b5beb8c471ae4f814748d5fb5c802dad)
1*6db064f3Skrw /*	$OpenBSD: disksubr.c,v 1.74 2022/10/11 23:39:08 krw Exp $	*/
23dbea441Sjason /*	$NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk Exp $ */
33dbea441Sjason 
43dbea441Sjason /*
53dbea441Sjason  * Copyright (c) 1994, 1995 Gordon W. Ross
63dbea441Sjason  * Copyright (c) 1994 Theo de Raadt
73dbea441Sjason  * All rights reserved.
83dbea441Sjason  *
93dbea441Sjason  * Redistribution and use in source and binary forms, with or without
103dbea441Sjason  * modification, are permitted provided that the following conditions
113dbea441Sjason  * are met:
123dbea441Sjason  * 1. Redistributions of source code must retain the above copyright
133dbea441Sjason  *    notice, this list of conditions and the following disclaimer.
143dbea441Sjason  * 2. Redistributions in binary form must reproduce the above copyright
153dbea441Sjason  *    notice, this list of conditions and the following disclaimer in the
163dbea441Sjason  *    documentation and/or other materials provided with the distribution.
17bed2b053Sderaadt  * 3. The name of the author may not be used to endorse or promote products
183dbea441Sjason  *    derived from this software without specific prior written permission
193dbea441Sjason  *
203dbea441Sjason  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
213dbea441Sjason  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
223dbea441Sjason  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
233dbea441Sjason  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
243dbea441Sjason  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
253dbea441Sjason  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
263dbea441Sjason  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
273dbea441Sjason  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
283dbea441Sjason  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
293dbea441Sjason  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303dbea441Sjason  */
313dbea441Sjason 
323dbea441Sjason #include <sys/param.h>
333dbea441Sjason #include <sys/systm.h>
343dbea441Sjason #include <sys/buf.h>
353dbea441Sjason #include <sys/disklabel.h>
363dbea441Sjason #include <sys/disk.h>
373dbea441Sjason 
383dbea441Sjason #include <dev/sun/disklabel.h>
393dbea441Sjason 
400748e129Sjason #include "cd.h"
413dbea441Sjason 
42*6db064f3Skrw static	int disklabel_sun_to_bsd(dev_t dev, struct sun_disklabel *,
43*6db064f3Skrw     struct disklabel *);
44eb1f9bf6Sderaadt static	int disklabel_bsd_to_sun(struct disklabel *, struct sun_disklabel *);
45e5be4e64Sderaadt static __inline u_int sun_extended_sum(struct sun_disklabel *, void *);
463dbea441Sjason 
470748e129Sjason #if NCD > 0
48c4071fd1Smillert extern void cdstrategy(struct buf *);
490748e129Sjason #endif
500748e129Sjason 
513dbea441Sjason /*
523dbea441Sjason  * Attempt to read a disk label from a device
5390e9e5d2Sderaadt  * using the indicated strategy routine.
543dbea441Sjason  * The label must be partly set up before this:
553dbea441Sjason  * secpercyl, secsize and anything required for a block i/o read
563dbea441Sjason  * operation in the driver's strategy/start routines
573dbea441Sjason  * must be filled in before calling us.
583dbea441Sjason  */
59df591ed6Sderaadt int
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,int spoofonly)60aa0d1f53Sderaadt readdisklabel(dev_t dev, void (*strat)(struct buf *),
61c326f117Sderaadt     struct disklabel *lp, int spoofonly)
623dbea441Sjason {
633dbea441Sjason 	struct sun_disklabel *slp;
64eb1f9bf6Sderaadt 	struct buf *bp = NULL;
65df591ed6Sderaadt 	int error;
663dbea441Sjason 
67df591ed6Sderaadt 	if ((error = initdisklabel(lp)))
682cbe5958Skrw 		goto done;
696ab0bb66Skrw 	lp->d_flags |= D_VENDOR;
703dbea441Sjason 
71eb1f9bf6Sderaadt 	/*
72eb1f9bf6Sderaadt 	 * On sparc64 we check for a CD label first, because our
73eb1f9bf6Sderaadt 	 * CD install media contains both sparc & sparc64 labels.
74eb1f9bf6Sderaadt 	 * We want the sparc64 machine to find the "CD label", not
75fd03e8bdSmiod 	 * the SunOS label, for loading its kernel.
76eb1f9bf6Sderaadt 	 */
771cb819b0Sderaadt #if NCD > 0
781cb819b0Sderaadt 	if (strat == cdstrategy) {
791cb819b0Sderaadt #if defined(CD9660)
8070d28270Sderaadt 		if (iso_disklabelspoof(dev, strat, lp) == 0)
812cbe5958Skrw 			goto done;
8290a67f16Sjason #endif
831cb819b0Sderaadt #if defined(UDF)
8470d28270Sderaadt 		if (udf_disklabelspoof(dev, strat, lp) == 0)
852cbe5958Skrw 			goto done;
861cb819b0Sderaadt #endif
871cb819b0Sderaadt 	}
881cb819b0Sderaadt #endif /* NCD > 0 */
8990a67f16Sjason 
90602e192cSderaadt 	/* get buffer and initialize it */
91b986024fSnatano 	bp = geteblk(lp->d_secsize);
923dbea441Sjason 	bp->b_dev = dev;
93eb1f9bf6Sderaadt 
94eb1f9bf6Sderaadt 	if (spoofonly)
95eb1f9bf6Sderaadt 		goto doslabel;
96eb1f9bf6Sderaadt 
97203b7c41Skrw 	error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR));
98203b7c41Skrw 	if (error)
992cbe5958Skrw 		goto done;
1003dbea441Sjason 
101eb1f9bf6Sderaadt 	slp = (struct sun_disklabel *)bp->b_data;
1022cbe5958Skrw 	if (slp->sl_magic == SUN_DKMAGIC) {
103*6db064f3Skrw 		error = disklabel_sun_to_bsd(bp->b_dev, slp, lp);
1042cbe5958Skrw 		goto done;
1052cbe5958Skrw 	}
1063dbea441Sjason 
107*6db064f3Skrw 	error = checkdisklabel(bp->b_dev, bp->b_data + LABELOFFSET, lp, 0,
108*6db064f3Skrw 	    DL_GETDSIZE(lp));
109df591ed6Sderaadt 	if (error == 0)
1102cbe5958Skrw 		goto done;
1113dbea441Sjason 
112eb1f9bf6Sderaadt doslabel:
113df591ed6Sderaadt 	error = readdoslabel(bp, strat, lp, NULL, spoofonly);
114df591ed6Sderaadt 	if (error == 0)
115eb1f9bf6Sderaadt 		goto done;
116eb1f9bf6Sderaadt 
117eb1f9bf6Sderaadt 	/* A CD9660/UDF label may be on a non-CD drive, so recheck */
1180748e129Sjason #if defined(CD9660)
119df591ed6Sderaadt 	error = iso_disklabelspoof(dev, strat, lp);
120df591ed6Sderaadt 	if (error == 0)
1212cbe5958Skrw 		goto done;
1220748e129Sjason #endif
1231cb819b0Sderaadt #if defined(UDF)
124df591ed6Sderaadt 	error = udf_disklabelspoof(dev, strat, lp);
125df591ed6Sderaadt 	if (error == 0)
1262cbe5958Skrw 		goto done;
1271cb819b0Sderaadt #endif
1282cbe5958Skrw 
1292cbe5958Skrw done:
1302cbe5958Skrw 	if (bp) {
1312d6afe32Sderaadt 		bp->b_flags |= B_INVAL;
1322cbe5958Skrw 		brelse(bp);
1332cbe5958Skrw 	}
134a545cc80Skrw 	disk_change = 1;
135df591ed6Sderaadt 	return (error);
1363dbea441Sjason }
1373dbea441Sjason 
1383dbea441Sjason /*
1393dbea441Sjason  * Write disk label back to device after modification.
1403dbea441Sjason  */
1413dbea441Sjason int
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp)142c326f117Sderaadt writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
1433dbea441Sjason {
1442d6afe32Sderaadt 	struct buf *bp = NULL;
1453dbea441Sjason 	int error;
1463dbea441Sjason 
147602e192cSderaadt 	/* get buffer and initialize it */
148b986024fSnatano 	bp = geteblk(lp->d_secsize);
149eb1f9bf6Sderaadt 	bp->b_dev = dev;
150eb1f9bf6Sderaadt 
151eb1f9bf6Sderaadt 	error = disklabel_bsd_to_sun(lp, (struct sun_disklabel *)bp->b_data);
152aa0d1f53Sderaadt 	if (error)
1532d6afe32Sderaadt 		goto done;
1543dbea441Sjason 
1553dbea441Sjason 	/* Write out the updated label. */
1563dbea441Sjason 	bp->b_blkno = LABELSECTOR;
1573dbea441Sjason 	bp->b_bcount = lp->d_secsize;
1580189133dSkrw 	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
159e08c5f56Skrw 	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
1603dbea441Sjason 	(*strat)(bp);
1613dbea441Sjason 	error = biowait(bp);
1623dbea441Sjason 
1632d6afe32Sderaadt done:
1642d6afe32Sderaadt 	if (bp) {
1652d6afe32Sderaadt 		bp->b_flags |= B_INVAL;
1662d6afe32Sderaadt 		brelse(bp);
1672d6afe32Sderaadt 	}
168a545cc80Skrw 	disk_change = 1;
1693dbea441Sjason 	return (error);
1703dbea441Sjason }
1713dbea441Sjason 
1723dbea441Sjason /************************************************************************
1733dbea441Sjason  *
1743dbea441Sjason  * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
1753dbea441Sjason  * and then substantially rewritten by Gordon W. Ross
1763dbea441Sjason  *
1773dbea441Sjason  ************************************************************************/
1783dbea441Sjason 
1793dbea441Sjason /* What partition types to assume for Sun disklabels: */
1803dbea441Sjason static u_char
18154d50441Sjason sun_fstypes[16] = {
1823dbea441Sjason 	FS_BSDFFS,	/* a */
1833dbea441Sjason 	FS_SWAP,	/* b */
18454d50441Sjason 	FS_UNUSED,	/* c - whole disk */
1853dbea441Sjason 	FS_BSDFFS,	/* d */
1863dbea441Sjason 	FS_BSDFFS,	/* e */
1873dbea441Sjason 	FS_BSDFFS,	/* f */
1883dbea441Sjason 	FS_BSDFFS,	/* g */
1893dbea441Sjason 	FS_BSDFFS,	/* h */
19054d50441Sjason 	FS_BSDFFS,	/* i */
19154d50441Sjason 	FS_BSDFFS,	/* j */
19254d50441Sjason 	FS_BSDFFS,	/* k */
19354d50441Sjason 	FS_BSDFFS,	/* l */
19454d50441Sjason 	FS_BSDFFS,	/* m */
19554d50441Sjason 	FS_BSDFFS,	/* n */
19654d50441Sjason 	FS_BSDFFS,	/* o */
197aa0d1f53Sderaadt 	FS_BSDFFS	/* p */
1983dbea441Sjason };
1993dbea441Sjason 
2003dbea441Sjason /*
20154d50441Sjason  * Given a struct sun_disklabel, assume it has an extended partition
20254d50441Sjason  * table and compute the correct value for sl_xpsum.
20354d50441Sjason  */
20454d50441Sjason static __inline u_int
sun_extended_sum(struct sun_disklabel * sl,void * end)205e5be4e64Sderaadt sun_extended_sum(struct sun_disklabel *sl, void *end)
20654d50441Sjason {
207aa0d1f53Sderaadt 	u_int sum, *xp, *ep;
20854d50441Sjason 
20954d50441Sjason 	xp = (u_int *)&sl->sl_xpmag;
210e5be4e64Sderaadt 	ep = (u_int *)end;
21154d50441Sjason 
212aa0d1f53Sderaadt 	sum = 0;
21354d50441Sjason 	for (; xp < ep; xp++)
214aa0d1f53Sderaadt 		sum += *xp;
215aa0d1f53Sderaadt 	return (sum);
21654d50441Sjason }
21754d50441Sjason 
21854d50441Sjason /*
2193dbea441Sjason  * Given a SunOS disk label, set lp to a BSD disk label.
2203dbea441Sjason  * The BSD label is cleared out before this is called.
2213dbea441Sjason  */
222df591ed6Sderaadt static int
disklabel_sun_to_bsd(dev_t dev,struct sun_disklabel * sl,struct disklabel * lp)223*6db064f3Skrw disklabel_sun_to_bsd(dev_t dev, struct sun_disklabel *sl, struct disklabel *lp)
2243dbea441Sjason {
225dd20e1a2Skrw 	struct sun_preamble *preamble = (struct sun_preamble *)sl;
226a49b0a0bStsi 	struct sun_partinfo *ppp;
227dd20e1a2Skrw 	struct sun_dkpart *spp;
228dd20e1a2Skrw 	struct partition *npp;
229eb1f9bf6Sderaadt 	u_short cksum = 0, *sp1, *sp2;
230dd20e1a2Skrw 	int i, secpercyl;
2313dbea441Sjason 
2323dbea441Sjason 	/* Verify the XOR check. */
2333dbea441Sjason 	sp1 = (u_short *)sl;
2343dbea441Sjason 	sp2 = (u_short *)(sl + 1);
2353dbea441Sjason 	while (sp1 < sp2)
2363dbea441Sjason 		cksum ^= *sp1++;
2373dbea441Sjason 	if (cksum != 0)
238df591ed6Sderaadt 		return (EINVAL);	/* SunOS disk label, bad checksum */
2393dbea441Sjason 
2403dbea441Sjason 	/* Format conversion. */
2413dbea441Sjason 	lp->d_magic = DISKMAGIC;
2423dbea441Sjason 	lp->d_magic2 = DISKMAGIC;
243eb1f9bf6Sderaadt 	lp->d_flags = D_VENDOR;
2443dbea441Sjason 	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
2453dbea441Sjason 
246f2af9bfeSkrw 	lp->d_secsize = DEV_BSIZE;
2473dbea441Sjason 	lp->d_nsectors = sl->sl_nsectors;
2483dbea441Sjason 	lp->d_ntracks = sl->sl_ntracks;
2493dbea441Sjason 	lp->d_ncylinders = sl->sl_ncylinders;
2503dbea441Sjason 
2513dbea441Sjason 	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
2523dbea441Sjason 	lp->d_secpercyl = secpercyl;
253af4e92efSmiod 	/* If unset or initialized as full disk, permit refinement */
254af4e92efSmiod 	if (DL_GETDSIZE(lp) == 0 || DL_GETDSIZE(lp) == MAXDISKSIZE)
2551c51b504Skrw 		DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders);
256eb1f9bf6Sderaadt 	lp->d_version = 1;
2573dbea441Sjason 
2583c8dd627Sderaadt 	memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid));
259d8b1e0ecSjsing 
2603dbea441Sjason 	lp->d_acylinders = sl->sl_acylinders;
2613dbea441Sjason 
26254d50441Sjason 	lp->d_npartitions = MAXPARTITIONS;
2633dbea441Sjason 
2643dbea441Sjason 	for (i = 0; i < 8; i++) {
2653dbea441Sjason 		spp = &sl->sl_part[i];
2663dbea441Sjason 		npp = &lp->d_partitions[i];
267e16633b4Sderaadt 		DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
268e16633b4Sderaadt 		DL_SETPSIZE(npp, spp->sdkp_nsectors);
269e16633b4Sderaadt 		if (DL_GETPSIZE(npp) == 0) {
2703dbea441Sjason 			npp->p_fstype = FS_UNUSED;
2713dbea441Sjason 		} else {
2723dbea441Sjason 			npp->p_fstype = sun_fstypes[i];
2733dbea441Sjason 			if (npp->p_fstype == FS_BSDFFS) {
2743dbea441Sjason 				/*
2753dbea441Sjason 				 * The sun label does not store the FFS fields,
2763dbea441Sjason 				 * so just set them with default values here.
2773dbea441Sjason 				 */
278ddfcbf38Sotto 				npp->p_fragblock =
279ddfcbf38Sotto 				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
2803dbea441Sjason 				npp->p_cpg = 16;
2813dbea441Sjason 			}
2823dbea441Sjason 		}
2833dbea441Sjason 	}
2843dbea441Sjason 
28554d50441Sjason 	/* Clear "extended" partition info, tentatively */
28654d50441Sjason 	for (i = 0; i < SUNXPART; i++) {
28754d50441Sjason 		npp = &lp->d_partitions[i+8];
288e16633b4Sderaadt 		DL_SETPOFFSET(npp, 0);
289e16633b4Sderaadt 		DL_SETPSIZE(npp, 0);
29054d50441Sjason 		npp->p_fstype = FS_UNUSED;
29154d50441Sjason 	}
29254d50441Sjason 
293e5be4e64Sderaadt 	/* Check to see if there's an "extended" partition table
294e5be4e64Sderaadt 	 * SL_XPMAG partitions had checksums up to just before the
295e5be4e64Sderaadt 	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
296e5be4e64Sderaadt 	 * checksums up to the just before the (new) sl_xxx1 variable.
297d7db92a1Sjsing 	 * Also, disklabels created prior to the addition of sl_uid will
298d7db92a1Sjsing 	 * have a checksum to just before the sl_uid variable.
299e5be4e64Sderaadt 	 */
300e5be4e64Sderaadt 	if ((sl->sl_xpmag == SL_XPMAG &&
301e5be4e64Sderaadt 	    sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) ||
302e5be4e64Sderaadt 	    (sl->sl_xpmag == SL_XPMAGTYP &&
303d7db92a1Sjsing 	    sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) ||
304d7db92a1Sjsing 	    (sl->sl_xpmag == SL_XPMAGTYP &&
305e5be4e64Sderaadt 	    sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) {
30654d50441Sjason 		/*
30754d50441Sjason 		 * There is.  Copy over the "extended" partitions.
30854d50441Sjason 		 * This code parallels the loop for partitions a-h.
30954d50441Sjason 		 */
31054d50441Sjason 		for (i = 0; i < SUNXPART; i++) {
31154d50441Sjason 			spp = &sl->sl_xpart[i];
31254d50441Sjason 			npp = &lp->d_partitions[i+8];
313e16633b4Sderaadt 			DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
314e16633b4Sderaadt 			DL_SETPSIZE(npp, spp->sdkp_nsectors);
315e16633b4Sderaadt 			if (DL_GETPSIZE(npp) == 0) {
31654d50441Sjason 				npp->p_fstype = FS_UNUSED;
31754d50441Sjason 				continue;
31854d50441Sjason 			}
31954d50441Sjason 			npp->p_fstype = sun_fstypes[i+8];
32054d50441Sjason 			if (npp->p_fstype == FS_BSDFFS) {
321ddfcbf38Sotto 				npp->p_fragblock =
322902b3654Sderaadt 				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
32354d50441Sjason 				npp->p_cpg = 16;
32454d50441Sjason 			}
32554d50441Sjason 		}
326a49b0a0bStsi 		if (sl->sl_xpmag == SL_XPMAGTYP) {
327346fa163Sderaadt 			for (i = 0; i < MAXPARTITIONS; i++) {
328346fa163Sderaadt 				npp = &lp->d_partitions[i];
329346fa163Sderaadt 				npp->p_fstype = sl->sl_types[i];
330346fa163Sderaadt 				npp->p_fragblock = sl->sl_fragblock[i];
331346fa163Sderaadt 				npp->p_cpg = sl->sl_cpg[i];
332346fa163Sderaadt 			}
33354d50441Sjason 		}
334dd20e1a2Skrw 	} else if (preamble->sl_nparts <= 8) {
335a49b0a0bStsi 		/*
336a49b0a0bStsi 		 * A more traditional Sun label.  Recognise certain filesystem
337a49b0a0bStsi 		 * types from it, if they are available.
338a49b0a0bStsi 		 */
339dd20e1a2Skrw 		i = preamble->sl_nparts;
340dd20e1a2Skrw 		if (i == 0)
341dd20e1a2Skrw 			i = 8;
342dd20e1a2Skrw 
343dd20e1a2Skrw 		npp = &lp->d_partitions[i-1];
344dd20e1a2Skrw 		ppp = &preamble->sl_part[i-1];
345dd20e1a2Skrw 		for (; i > 0; i--, npp--, ppp--) {
346a49b0a0bStsi 			if (npp->p_size == 0)
347a49b0a0bStsi 				continue;
348a49b0a0bStsi 			if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0))
349a49b0a0bStsi 				continue;
350a49b0a0bStsi 
351a49b0a0bStsi 			switch (ppp->spi_tag) {
352a49b0a0bStsi 			case SPTAG_SUNOS_ROOT:
353a49b0a0bStsi 			case SPTAG_SUNOS_USR:
354a49b0a0bStsi 			case SPTAG_SUNOS_VAR:
355a49b0a0bStsi 			case SPTAG_SUNOS_HOME:
356a49b0a0bStsi 				npp->p_fstype = FS_BSDFFS;
357a49b0a0bStsi 				npp->p_fragblock =
358a49b0a0bStsi 				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
359a49b0a0bStsi 				npp->p_cpg = 16;
360a49b0a0bStsi 				break;
361a49b0a0bStsi 			case SPTAG_LINUX_EXT2:
362a49b0a0bStsi 				npp->p_fstype = FS_EXT2FS;
363a49b0a0bStsi 				break;
364a49b0a0bStsi 			default:
365dd20e1a2Skrw 				/* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */
366a49b0a0bStsi 				npp->p_fstype = FS_UNUSED;
367a49b0a0bStsi 				break;
368a49b0a0bStsi 			}
369a49b0a0bStsi 		}
370a49b0a0bStsi 	}
37154d50441Sjason 
3723dbea441Sjason 	lp->d_checksum = 0;
3733dbea441Sjason 	lp->d_checksum = dkcksum(lp);
374*6db064f3Skrw 	return (checkdisklabel(dev, lp, lp, 0, DL_GETDSIZE(lp)));
3753dbea441Sjason }
3763dbea441Sjason 
3773dbea441Sjason /*
3783dbea441Sjason  * Given a BSD disk label, update the Sun disklabel
3793dbea441Sjason  * pointed to by cp with the new info.  Note that the
3803dbea441Sjason  * Sun disklabel may have other info we need to keep.
3813dbea441Sjason  */
3823dbea441Sjason static int
disklabel_bsd_to_sun(struct disklabel * lp,struct sun_disklabel * sl)383eb1f9bf6Sderaadt disklabel_bsd_to_sun(struct disklabel *lp, struct sun_disklabel *sl)
3843dbea441Sjason {
3853dbea441Sjason 	struct partition *npp;
3863dbea441Sjason 	struct sun_dkpart *spp;
3873dbea441Sjason 	int i, secpercyl;
3883dbea441Sjason 	u_short cksum, *sp1, *sp2;
3893dbea441Sjason 
39054d50441Sjason 	/* Enforce preconditions */
391f2af9bfeSkrw 	if (lp->d_secsize != DEV_BSIZE || lp->d_nsectors == 0 ||
392f2af9bfeSkrw 	    lp->d_ntracks == 0)
3933dbea441Sjason 		return (EINVAL);
3943dbea441Sjason 
39554d50441Sjason 	/* Format conversion. */
3961732b2a7Sderaadt 	bzero(sl, sizeof(*sl));
3973dbea441Sjason 	memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
3983dbea441Sjason 	sl->sl_pcylinders = lp->d_ncylinders + lp->d_acylinders; /* XXX */
3993dbea441Sjason 	sl->sl_ncylinders = lp->d_ncylinders;
4003dbea441Sjason 	sl->sl_acylinders = lp->d_acylinders;
4013dbea441Sjason 	sl->sl_ntracks = lp->d_ntracks;
4023dbea441Sjason 	sl->sl_nsectors = lp->d_nsectors;
4033dbea441Sjason 
4043c8dd627Sderaadt 	memcpy(&sl->sl_uid, &lp->d_uid, sizeof(lp->d_uid));
405d8b1e0ecSjsing 
4063dbea441Sjason 	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
4073dbea441Sjason 	for (i = 0; i < 8; i++) {
4083dbea441Sjason 		spp = &sl->sl_part[i];
4093dbea441Sjason 		npp = &lp->d_partitions[i];
4101d55161dSkrw 		spp->sdkp_cyloffset = 0;
4111d55161dSkrw 		spp->sdkp_nsectors = 0;
4121d55161dSkrw 		if (DL_GETPSIZE(npp)) {
413e16633b4Sderaadt 			if (DL_GETPOFFSET(npp) % secpercyl)
4143dbea441Sjason 				return (EINVAL);
415e16633b4Sderaadt 			spp->sdkp_cyloffset = DL_GETPOFFSET(npp) / secpercyl;
416e16633b4Sderaadt 			spp->sdkp_nsectors = DL_GETPSIZE(npp);
4173dbea441Sjason 		}
4181d55161dSkrw 	}
4193dbea441Sjason 	sl->sl_magic = SUN_DKMAGIC;
4203dbea441Sjason 
42154d50441Sjason 	for (i = 0; i < SUNXPART; i++) {
42254d50441Sjason 		spp = &sl->sl_xpart[i];
42354d50441Sjason 		npp = &lp->d_partitions[i+8];
4241d55161dSkrw 		spp->sdkp_cyloffset = 0;
4251d55161dSkrw 		spp->sdkp_nsectors = 0;
4261d55161dSkrw 		if (DL_GETPSIZE(npp)) {
427e16633b4Sderaadt 			if (DL_GETPOFFSET(npp) % secpercyl)
42854d50441Sjason 				return (EINVAL);
4291d55161dSkrw 			spp->sdkp_cyloffset = DL_GETPOFFSET(npp) / secpercyl;
4301d55161dSkrw 			spp->sdkp_nsectors = DL_GETPSIZE(npp);
4311d55161dSkrw 		}
43254d50441Sjason 	}
433346fa163Sderaadt 	for (i = 0; i < MAXPARTITIONS; i++) {
434346fa163Sderaadt 		npp = &lp->d_partitions[i];
435346fa163Sderaadt 		sl->sl_types[i] = npp->p_fstype;
436346fa163Sderaadt 		sl->sl_fragblock[i] = npp->p_fragblock;
437346fa163Sderaadt 		sl->sl_cpg[i] = npp->p_cpg;
438346fa163Sderaadt 	}
439e5be4e64Sderaadt 	sl->sl_xpmag = SL_XPMAGTYP;
440e5be4e64Sderaadt 	sl->sl_xpsum = sun_extended_sum(sl, &sl->sl_xxx1);
44154d50441Sjason 
44254d50441Sjason 	/* Correct the XOR check. */
4433dbea441Sjason 	sp1 = (u_short *)sl;
4443dbea441Sjason 	sp2 = (u_short *)(sl + 1);
4453dbea441Sjason 	sl->sl_cksum = cksum = 0;
4463dbea441Sjason 	while (sp1 < sp2)
4473dbea441Sjason 		cksum ^= *sp1++;
4483dbea441Sjason 	sl->sl_cksum = cksum;
4493dbea441Sjason 
4503dbea441Sjason 	return (0);
4513dbea441Sjason }
452