Home | History | Annotate | Line # | Download | only in arm
      1 /*	$NetBSD: disksubr_acorn.c,v 1.14 2024/01/15 19:34:13 andvar Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998 Christopher G. Demetriou.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Christopher G. Demetriou
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
     35  * All rights reserved.
     36  *
     37  * Redistribution and use in source and binary forms, with or without
     38  * modification, are permitted provided that the following conditions
     39  * are met:
     40  * 1. Redistributions of source code must retain the above copyright
     41  *    notice, this list of conditions and the following disclaimer.
     42  * 2. Redistributions in binary form must reproduce the above copyright
     43  *    notice, this list of conditions and the following disclaimer in the
     44  *    documentation and/or other materials provided with the distribution.
     45  * 3. Neither the name of the University nor the names of its contributors
     46  *    may be used to endorse or promote products derived from this software
     47  *    without specific prior written permission.
     48  *
     49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     59  * SUCH DAMAGE.
     60  *
     61  *	from: @(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
     62  */
     63 
     64 /*
     65  * Copyright (c) 1995 Mark Brinicombe
     66  * All rights reserved.
     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  *	from: @(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
     97  */
     98 
     99 #include <sys/cdefs.h>
    100 __KERNEL_RCSID(0, "$NetBSD: disksubr_acorn.c,v 1.14 2024/01/15 19:34:13 andvar Exp $");
    101 
    102 #include <sys/param.h>
    103 #include <sys/systm.h>
    104 #include <sys/buf.h>
    105 #include <sys/disklabel.h>
    106 
    107 static int filecore_checksum(u_char *);
    108 
    109 /*
    110  * static int filecore_checksum(u_char *bootblock)
    111  *
    112  * Calculates the filecore boot block checksum. This is used to validate
    113  * a filecore boot block on the disk.  If a boot block is validated then
    114  * it is used to locate the partition table. If the boot block is not
    115  * validated, it is assumed that the whole disk is NetBSD.
    116  *
    117  * The basic algorithm is:
    118  *
    119  *	for (each byte in block, excluding checksum) {
    120  *		sum += byte;
    121  *		if (sum > 255)
    122  *			sum -= 255;
    123  *	}
    124  *
    125  * That's equivalent to summing all of the bytes in the block
    126  * (excluding the checksum byte, of course), then calculating the
    127  * checksum as "cksum = sum - ((sum - 1) / 255) * 255)".  That
    128  * expression may or may not yield a faster checksum function,
    129  * but it's easier to reason about.
    130  *
    131  * Note that if you have a block filled with bytes of a single
    132  * value "X" (regardless of that value!) and calculate the cksum
    133  * of the block (excluding the checksum byte), you will _always_
    134  * end up with a checksum of X.  (Do the math; that can be derived
    135  * from the checksum calculation function!)  That means that
    136  * blocks which contain bytes which all have the same value will
    137  * always checksum properly.  That's a _very_ unlikely occurrence
    138  * (probably impossible, actually) for a valid filecore boot block,
    139  * so we treat such blocks as invalid.
    140  */
    141 static int
    142 filecore_checksum(u_char *bootblock)
    143 {
    144 	u_char byte0, accum_diff;
    145 	u_int sum;
    146 	int i;
    147 
    148 	sum = 0;
    149 	accum_diff = 0;
    150 	byte0 = bootblock[0];
    151 
    152 	/*
    153 	 * Sum the contents of the block, keeping track of whether
    154 	 * or not all bytes are the same.  If 'accum_diff' ends up
    155 	 * being zero, all of the bytes are, in fact, the same.
    156 	 */
    157 	for (i = 0; i < 511; ++i) {
    158 		sum += bootblock[i];
    159 		accum_diff |= bootblock[i] ^ byte0;
    160 	}
    161 
    162 	/*
    163 	 * Check to see if the checksum byte is the same as the
    164 	 * rest of the bytes, too.  (Note that if all of the bytes
    165 	 * are the same except the checksum, a checksum compare
    166 	 * won't succeed, but that's not our problem.)
    167 	 */
    168 	accum_diff |= bootblock[i] ^ byte0;
    169 
    170 	/* All bytes in block are the same; call it invalid. */
    171 	if (accum_diff == 0)
    172 		return (-1);
    173 
    174 	return (sum - ((sum - 1) / 255) * 255);
    175 }
    176 
    177 
    178 int
    179 filecore_label_read(dev_t dev, void (*strat)(struct buf *),
    180 	struct disklabel *lp, struct cpu_disklabel *osdep,
    181 	const char **msgp,
    182 	int *cylp, int *netbsd_label_offp)
    183 {
    184 	struct filecore_bootblock *bb;
    185 	int heads;
    186 	int sectors;
    187 	int rv = 1;
    188 	int cyl, netbsdpartoff;
    189 	struct buf *bp;
    190 
    191 #ifdef __GNUC__
    192 	netbsdpartoff = 0;		/* XXX -Wuninitialized */
    193 #endif
    194 
    195 	/* get a buffer and initialize it */
    196         bp = geteblk((int)lp->d_secsize);
    197         bp->b_dev = dev;
    198 
    199 	/* read the Acorn filecore boot block */
    200 
    201 	bp->b_blkno = FILECORE_BOOT_SECTOR;
    202 	bp->b_bcount = lp->d_secsize;
    203 	bp->b_flags |= B_READ;
    204 	bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
    205 	(*strat)(bp);
    206 
    207 	/*
    208 	 * if successful, validate boot block and
    209 	 * locate partition table
    210 	 */
    211 
    212 	if (biowait(bp)) {
    213 		*msgp = "filecore boot block I/O error";
    214 		goto out;
    215 	}
    216 
    217 	bb = (struct filecore_bootblock *)bp->b_data;
    218 
    219 	/* Validate boot block */
    220 
    221 	if (bb->checksum != filecore_checksum((u_char *)bb)) {
    222 		/*
    223 		 * Invalid boot block so lets assume the
    224 		 *  entire disc is NetBSD
    225 		 */
    226 		rv = 0;
    227 		goto out;
    228 	}
    229 
    230 	/* Get some information from the boot block */
    231 
    232 	cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
    233 
    234 	heads = bb->heads;
    235 	sectors = bb->secspertrack;
    236 
    237 	/* Do we have a NETBSD partition table ? */
    238 
    239 	if (bb->partition_type == PARTITION_FORMAT_RISCBSD) {
    240 #ifdef DEBUG_LABEL
    241 		printf("%s; heads = %d nsectors = %d\n",
    242 		    __func__, heads, sectors);
    243 #endif
    244 		netbsdpartoff = cyl * heads * sectors;
    245 	} else if (bb->partition_type == PARTITION_FORMAT_RISCIX) {
    246 		struct riscix_partition_table *rpt;
    247 		int loop;
    248 
    249 		/*
    250 		 * We have a RISCiX partition table :-( groan
    251 		 *
    252 		 * Read the RISCiX partition table and see if
    253 		 * there is a NetBSD partition
    254 		 */
    255 
    256 		bp->b_blkno = cyl * heads * sectors;
    257 #ifdef DEBUG_LABEL
    258 		printf("%s: Found RiscIX partition table @ %" PRId64 "\n",
    259 		    __func__, bp->b_blkno);
    260 #endif
    261 		bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
    262 		bp->b_bcount = lp->d_secsize;
    263 		bp->b_oflags &= ~(BO_DONE);
    264 		bp->b_flags |= B_READ;
    265 		(*strat)(bp);
    266 
    267 		/*
    268 		 * if successful, locate disk label within block
    269 		 * and validate
    270 		 */
    271 
    272 		if (biowait(bp)) {
    273 			*msgp = "disk label I/O error";
    274 			goto out;
    275 		}
    276 
    277 		rpt = (struct riscix_partition_table *)bp->b_data;
    278 #ifdef DEBUG_LABEL
    279 		for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop)
    280 			printf("%s: p%d: %16s %08x %08x %08x\n", __func__,
    281 			    loop, rpt->partitions[loop].rp_name,
    282 			    rpt->partitions[loop].rp_start,
    283 			    rpt->partitions[loop].rp_length,
    284 			    rpt->partitions[loop].rp_type);
    285 #endif
    286 		for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) {
    287 			if (strcmp(rpt->partitions[loop].rp_name,
    288 			    "RiscBSD") == 0 ||
    289 			    strcmp(rpt->partitions[loop].rp_name,
    290 			    "NetBSD") == 0 ||
    291 			    strcmp(rpt->partitions[loop].rp_name,
    292 			    "Empty:") == 0) {
    293 				netbsdpartoff =
    294 				    rpt->partitions[loop].rp_start;
    295 				break;
    296 			}
    297 		}
    298 		if (loop == NRISCIX_PARTITIONS) {
    299 			*msgp = "NetBSD partition identifier string not found.";
    300 			goto out;
    301 		}
    302 	} else {
    303 		*msgp = "Invalid partition format";
    304 		goto out;
    305 	}
    306 
    307 	*cylp = cyl;
    308 	*netbsd_label_offp = netbsdpartoff;
    309 	*msgp = NULL;
    310 out:
    311         brelse(bp, 0);
    312 	return (rv);
    313 }
    314 
    315 
    316 /*
    317  * Return -1 not found, 0 found positive errno
    318  */
    319 int
    320 filecore_label_locate(dev_t dev,
    321 	void (*strat)(struct buf *),
    322 	struct disklabel *lp,
    323 	struct cpu_disklabel *osdep,
    324 	int *cylp, int *netbsd_label_offp)
    325 {
    326 	struct filecore_bootblock *bb;
    327 	int heads;
    328 	int sectors;
    329 	int rv;
    330 	int cyl, netbsdpartoff;
    331 	struct buf *bp;
    332 
    333 	/* get a buffer and initialize it */
    334         bp = geteblk((int)lp->d_secsize);
    335         bp->b_dev = dev;
    336 
    337 	/* read the filecore boot block */
    338 
    339 #ifdef DEBUG_LABEL
    340 	printf("%s: Reading boot block\n", __func__);
    341 #endif
    342 
    343 	bp->b_blkno = FILECORE_BOOT_SECTOR;
    344 	bp->b_bcount = lp->d_secsize;
    345 	bp->b_flags |= B_READ;
    346 	bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
    347 	(*strat)(bp);
    348 
    349 	/*
    350 	 * if successful, validate boot block and locate
    351 	 * partition table
    352 	 */
    353 
    354 	if ((rv = biowait(bp)) != 0) {
    355 		goto out;
    356 	}
    357 
    358 	bb = (struct filecore_bootblock *)bp->b_data;
    359 	rv = 0;
    360 
    361 	/* Validate boot block */
    362 
    363 	if (bb->checksum != filecore_checksum((u_char *)bb)) {
    364 		/*
    365 		 * Invalid boot block so lets assume the
    366 		 * entire disc is NetBSD
    367 		 */
    368 #ifdef DEBUG_LABEL
    369 		printf("%s: Bad filecore boot block (incorrect checksum)\n",
    370 		    __func__);
    371 #endif
    372 		rv = -1;
    373 		goto out;
    374 	}
    375 
    376 	/* Do we have a NetBSD partition ? */
    377 
    378 	if (bb->partition_type != PARTITION_FORMAT_RISCBSD) {
    379 #ifdef DEBUG_LABEL
    380 		printf("%s: Invalid partition format\n", __func__);
    381 #endif
    382 		rv = EINVAL;
    383 		goto out;
    384 	}
    385 
    386 	cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8);
    387 
    388 	heads = bb->heads;
    389 	sectors = bb->secspertrack;
    390 
    391 #ifdef DEBUG_LABEL
    392 	printf("%s: heads = %d nsectors = %d\n", __func__, heads, sectors);
    393 #endif
    394 
    395 	netbsdpartoff = cyl * heads * sectors;
    396 
    397 	*cylp = cyl;
    398 	*netbsd_label_offp = netbsdpartoff;
    399 out:
    400         brelse(bp, 0);
    401 	return (rv);
    402 }
    403