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