1*9bec9e43Sjsg /*	$OpenBSD: ufs_disksubr.c,v 1.7 2023/04/10 04:21:20 jsg Exp $	*/
296f141a8Smiod /*	$NetBSD: ufs_disksubr.c,v 1.2 2013/01/14 01:37:57 tsutsui Exp $	*/
396f141a8Smiod 
496f141a8Smiod /*
596f141a8Smiod  * Copyright (c) 1992 OMRON Corporation.
696f141a8Smiod  *
796f141a8Smiod  * This code is derived from software contributed to Berkeley by
896f141a8Smiod  * OMRON Corporation.
996f141a8Smiod  *
1096f141a8Smiod  * Redistribution and use in source and binary forms, with or without
1196f141a8Smiod  * modification, are permitted provided that the following conditions
1296f141a8Smiod  * are met:
1396f141a8Smiod  * 1. Redistributions of source code must retain the above copyright
1496f141a8Smiod  *    notice, this list of conditions and the following disclaimer.
1596f141a8Smiod  * 2. Redistributions in binary form must reproduce the above copyright
1696f141a8Smiod  *    notice, this list of conditions and the following disclaimer in the
1796f141a8Smiod  *    documentation and/or other materials provided with the distribution.
1896f141a8Smiod  * 3. All advertising materials mentioning features or use of this software
1996f141a8Smiod  *    must display the following acknowledgement:
2096f141a8Smiod  *	This product includes software developed by the University of
2196f141a8Smiod  *	California, Berkeley and its contributors.
2296f141a8Smiod  * 4. Neither the name of the University nor the names of its contributors
2396f141a8Smiod  *    may be used to endorse or promote products derived from this software
2496f141a8Smiod  *    without specific prior written permission.
2596f141a8Smiod  *
2696f141a8Smiod  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2796f141a8Smiod  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2896f141a8Smiod  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2996f141a8Smiod  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3096f141a8Smiod  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3196f141a8Smiod  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3296f141a8Smiod  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3396f141a8Smiod  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3496f141a8Smiod  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3596f141a8Smiod  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3696f141a8Smiod  * SUCH DAMAGE.
3796f141a8Smiod  *
3896f141a8Smiod  *	@(#)ufs_disksubr.c	8.1 (Berkeley) 6/10/93
3996f141a8Smiod  */
4096f141a8Smiod /*
4196f141a8Smiod  * Copyright (c) 1992, 1993
4296f141a8Smiod  *	The Regents of the University of California.  All rights reserved.
4396f141a8Smiod  *
4496f141a8Smiod  * This code is derived from software contributed to Berkeley by
4596f141a8Smiod  * OMRON Corporation.
4696f141a8Smiod  *
4796f141a8Smiod  * Redistribution and use in source and binary forms, with or without
4896f141a8Smiod  * modification, are permitted provided that the following conditions
4996f141a8Smiod  * are met:
5096f141a8Smiod  * 1. Redistributions of source code must retain the above copyright
5196f141a8Smiod  *    notice, this list of conditions and the following disclaimer.
5296f141a8Smiod  * 2. Redistributions in binary form must reproduce the above copyright
5396f141a8Smiod  *    notice, this list of conditions and the following disclaimer in the
5496f141a8Smiod  *    documentation and/or other materials provided with the distribution.
5596f141a8Smiod  * 3. Neither the name of the University nor the names of its contributors
5696f141a8Smiod  *    may be used to endorse or promote products derived from this software
5796f141a8Smiod  *    without specific prior written permission.
5896f141a8Smiod  *
5996f141a8Smiod  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6096f141a8Smiod  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6196f141a8Smiod  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6296f141a8Smiod  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6396f141a8Smiod  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6496f141a8Smiod  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6596f141a8Smiod  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6696f141a8Smiod  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6796f141a8Smiod  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6896f141a8Smiod  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6996f141a8Smiod  * SUCH DAMAGE.
7096f141a8Smiod  *
7196f141a8Smiod  *	@(#)ufs_disksubr.c	8.1 (Berkeley) 6/10/93
7296f141a8Smiod  */
7396f141a8Smiod 
7496f141a8Smiod /*
7596f141a8Smiod  * ufs_disksubr.c -- disk utility routines
7696f141a8Smiod  * by A.Fujita, FEB-26-1992
7796f141a8Smiod  */
7896f141a8Smiod 
7996f141a8Smiod #include <sys/param.h>
8096f141a8Smiod #include <sys/disklabel.h>
8196f141a8Smiod #include <dev/sun/disklabel.h>
8296f141a8Smiod #include <luna88k/stand/boot/samachdep.h>
8396f141a8Smiod #include <luna88k/stand/boot/scsireg.h>
8496f141a8Smiod 
8596f141a8Smiod #define	BBSIZE 8192
8696f141a8Smiod #define	LABEL_SIZE BBSIZE
8796f141a8Smiod u_char lbl_buff[LABEL_SIZE];
8896f141a8Smiod 
8996f141a8Smiod /*
9096f141a8Smiod  * Given a struct sun_disklabel, assume it has an extended partition
9196f141a8Smiod  * table and compute the correct value for sl_xpsum.
9296f141a8Smiod  */
9396f141a8Smiod static __inline u_int
sun_extended_sum(struct sun_disklabel * sl,void * end)9496f141a8Smiod sun_extended_sum(struct sun_disklabel *sl, void *end)
9596f141a8Smiod {
9696f141a8Smiod 	u_int sum, *xp, *ep;
9796f141a8Smiod 
9896f141a8Smiod 	xp = (u_int *)&sl->sl_xpmag;
9996f141a8Smiod 	ep = (u_int *)end;
10096f141a8Smiod 
10196f141a8Smiod 	sum = 0;
10296f141a8Smiod 	for (; xp < ep; xp++)
10396f141a8Smiod 		sum += *xp;
10496f141a8Smiod 	return (sum);
10596f141a8Smiod }
10696f141a8Smiod 
10796f141a8Smiod /*
10896f141a8Smiod  * Attempt to read a disk label from a device
109*9bec9e43Sjsg  * using the indicated strategy routine.
11096f141a8Smiod  * The label must be partly set up before this:
11196f141a8Smiod  * secpercyl and anything required in the strategy routine
11296f141a8Smiod  * (e.g., sector size) must be filled in before calling us.
11396f141a8Smiod  * Returns null on success and an error string on failure.
11496f141a8Smiod  */
11596f141a8Smiod char *
readdisklabel(struct scsi_softc * sc,uint tgt,struct disklabel * lp)116d2f66e2eSmiod readdisklabel(struct scsi_softc *sc, uint tgt, struct disklabel *lp)
11796f141a8Smiod {
11896f141a8Smiod 	u_char *bp = lbl_buff;
11996f141a8Smiod 	struct sun_disklabel *slp;
12096f141a8Smiod 	struct partition *npp;
12196f141a8Smiod 	struct sun_dkpart *spp;
12296f141a8Smiod 	u_short cksum = 0, *sp1, *sp2;
12396f141a8Smiod 	int i, secpercyl;
124d2f66e2eSmiod 	static struct scsi_generic_cdb cdb = {
12596f141a8Smiod 		6,
12696f141a8Smiod 		{ CMD_READ, 0, 0, 0, 1, 0 }
12796f141a8Smiod 	};
12896f141a8Smiod 
129862ef960Skrw 	if (DL_GETDSIZE(lp) == 0)
130862ef960Skrw 		DL_SETDSIZE(lp, 0x1fffffff);
13196f141a8Smiod 	lp->d_npartitions = 1;
132862ef960Skrw 	if (DL_GETPSIZE(&lp->d_partitions[0]) == 0)
133862ef960Skrw 		DL_SETPSIZE(&lp->d_partitions[0], 0x1fffffff);
134862ef960Skrw 	DL_SETPSIZE(&lp->d_partitions[0], 0);
13596f141a8Smiod 
136d2f66e2eSmiod 	if (scsi_immed_command(sc, tgt, 0, &cdb, bp, DEV_BSIZE) != 0)
13796f141a8Smiod 		return "I/O error";
13896f141a8Smiod 
13996f141a8Smiod 	slp = (struct sun_disklabel *)bp;
14096f141a8Smiod 	if (slp->sl_magic != SUN_DKMAGIC)
14196f141a8Smiod 		return "no disk label";
14296f141a8Smiod 
14396f141a8Smiod 	sp1 = (u_short *)slp;
14496f141a8Smiod 	sp2 = (u_short *)(slp + 1);
14596f141a8Smiod 	while (sp1 < sp2)
14696f141a8Smiod 		cksum ^= *sp1++;
14796f141a8Smiod 	if (cksum != 0)
14896f141a8Smiod 		return "disk label corrupted";
14996f141a8Smiod 
15096f141a8Smiod 	lp->d_magic = DISKMAGIC;
15196f141a8Smiod 	lp->d_magic2 = DISKMAGIC;
15296f141a8Smiod 	memcpy(lp->d_packname, slp->sl_text, sizeof(lp->d_packname));
15396f141a8Smiod 	lp->d_nsectors = slp->sl_nsectors;
15496f141a8Smiod 	lp->d_ntracks = slp->sl_ntracks;
15596f141a8Smiod 	lp->d_ncylinders = slp->sl_ncylinders;
15696f141a8Smiod 
15796f141a8Smiod 	secpercyl = slp->sl_nsectors * slp->sl_ntracks;
15896f141a8Smiod 	lp->d_secpercyl = secpercyl;
15996f141a8Smiod 	if (DL_GETDSIZE(lp) == 0)
160fd08467eSkrw 		DL_SETDSIZE(lp, (u_int64_t)secpercyl * slp->sl_ncylinders);
16196f141a8Smiod 	lp->d_version = 1;
16296f141a8Smiod 
16396f141a8Smiod 	memcpy(&lp->d_uid, &slp->sl_uid, sizeof(slp->sl_uid));
16496f141a8Smiod 
16596f141a8Smiod 	lp->d_acylinders = slp->sl_acylinders;
16696f141a8Smiod 
16796f141a8Smiod 	lp->d_npartitions = MAXPARTITIONS;
16896f141a8Smiod 
16996f141a8Smiod 	for (i = 0; i < 8; i++) {
17096f141a8Smiod 		spp = &slp->sl_part[i];
17196f141a8Smiod 		npp = &lp->d_partitions[i];
17296f141a8Smiod 		/* UniOS label uses blkoffset, not cyloffset */
17396f141a8Smiod 		DL_SETPOFFSET(npp, spp->sdkp_cyloffset);
17496f141a8Smiod 		DL_SETPSIZE(npp, spp->sdkp_nsectors);
17596f141a8Smiod 		if (DL_GETPSIZE(npp) == 0) {
17696f141a8Smiod 			npp->p_fstype = FS_UNUSED;
17796f141a8Smiod 		} else {
17896f141a8Smiod 			npp->p_fstype = i == 2 ? FS_UNUSED :
17996f141a8Smiod 			    i == 1 ? FS_SWAP : FS_BSDFFS;
18096f141a8Smiod 			if (npp->p_fstype == FS_BSDFFS) {
18196f141a8Smiod 				/*
18296f141a8Smiod 				 * The sun label does not store the FFS fields,
18396f141a8Smiod 				 * so just set them with default values here.
18496f141a8Smiod 				 */
18596f141a8Smiod 				npp->p_fragblock = 8 | 3
18696f141a8Smiod 				    /* DISKLABELV1_FFS_FRAGBLOCK(2048, 8); */ ;
18796f141a8Smiod 				npp->p_cpg = 16;
18896f141a8Smiod 			}
18996f141a8Smiod 		}
19096f141a8Smiod 	}
19196f141a8Smiod 
19296f141a8Smiod 	/*
19396f141a8Smiod 	 * XXX BandAid XXX
19496f141a8Smiod 	 * UniOS rootfs sits on part c which don't begin at sect 0,
19596f141a8Smiod 	 * and impossible to mount.  Thus, make it usable as part b.
19696f141a8Smiod 	 * XXX how to setup a swap partition on disks shared with UniOS???
19796f141a8Smiod 	 */
19896f141a8Smiod 	if (slp->sl_rpm == 0 && DL_GETPOFFSET(&lp->d_partitions[2]) != 0) {
19996f141a8Smiod 		lp->d_partitions[1] = lp->d_partitions[2];
20096f141a8Smiod 		lp->d_partitions[1].p_fstype = FS_BSDFFS;
20196f141a8Smiod 	}
20296f141a8Smiod 
20396f141a8Smiod 	/* Clear "extended" partition info, tentatively */
20496f141a8Smiod 	for (i = 0; i < SUNXPART; i++) {
20596f141a8Smiod 		npp = &lp->d_partitions[i+8];
20696f141a8Smiod 		DL_SETPOFFSET(npp, 0);
20796f141a8Smiod 		DL_SETPSIZE(npp, 0);
20896f141a8Smiod 		npp->p_fstype = FS_UNUSED;
20996f141a8Smiod 	}
21096f141a8Smiod 
21196f141a8Smiod 	/* Check to see if there's an "extended" partition table
21296f141a8Smiod 	 * SL_XPMAG partitions had checksums up to just before the
21396f141a8Smiod 	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
21496f141a8Smiod 	 * checksums up to the just before the (new) sl_xxx1 variable.
21596f141a8Smiod 	 */
21696f141a8Smiod 	if ((slp->sl_xpmag == SL_XPMAG &&
21796f141a8Smiod 	    sun_extended_sum(slp, &slp->sl_types) == slp->sl_xpsum) ||
21896f141a8Smiod 	    (slp->sl_xpmag == SL_XPMAGTYP &&
21996f141a8Smiod 	    sun_extended_sum(slp, &slp->sl_xxx1) == slp->sl_xpsum)) {
22096f141a8Smiod 		/*
22196f141a8Smiod 		 * There is.  Copy over the "extended" partitions.
22296f141a8Smiod 		 * This code parallels the loop for partitions a-h.
22396f141a8Smiod 		 */
22496f141a8Smiod 		for (i = 0; i < SUNXPART; i++) {
22596f141a8Smiod 			spp = &slp->sl_xpart[i];
22696f141a8Smiod 			npp = &lp->d_partitions[i+8];
22796f141a8Smiod 			DL_SETPOFFSET(npp, spp->sdkp_cyloffset);
22896f141a8Smiod 			DL_SETPSIZE(npp, spp->sdkp_nsectors);
22996f141a8Smiod 			if (DL_GETPSIZE(npp) == 0) {
23096f141a8Smiod 				npp->p_fstype = FS_UNUSED;
23196f141a8Smiod 				continue;
23296f141a8Smiod 			}
23396f141a8Smiod 			npp->p_fstype = FS_BSDFFS;
23496f141a8Smiod 			if (npp->p_fstype == FS_BSDFFS) {
23596f141a8Smiod 				npp->p_fragblock = 8 | 3
23696f141a8Smiod 				    /* DISKLABELV1_FFS_FRAGBLOCK(2048, 8); */ ;
23796f141a8Smiod 				npp->p_cpg = 16;
23896f141a8Smiod 			}
23996f141a8Smiod 		}
24096f141a8Smiod 		if (slp->sl_xpmag == SL_XPMAGTYP) {
24196f141a8Smiod 			for (i = 0; i < MAXPARTITIONS; i++) {
24296f141a8Smiod 				npp = &lp->d_partitions[i];
24396f141a8Smiod 				npp->p_fstype = slp->sl_types[i];
24496f141a8Smiod 				npp->p_fragblock = slp->sl_fragblock[i];
24596f141a8Smiod 				npp->p_cpg = slp->sl_cpg[i];
24696f141a8Smiod 			}
24796f141a8Smiod 		}
24896f141a8Smiod 	}
24996f141a8Smiod 
25096f141a8Smiod 	lp->d_checksum = 0;
25196f141a8Smiod 	lp->d_checksum = dkcksum(lp);
25296f141a8Smiod 
25396f141a8Smiod 	return NULL;
25496f141a8Smiod }
255