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