1 /* $NetBSD: disksubr_acorn.c,v 1.10 2009/03/15 22:23:16 cegger 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.10 2009/03/15 22:23:16 cegger 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 occurence 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 /* printf("heads = %d nsectors = %d\n", heads, sectors);*/ 241 netbsdpartoff = cyl * heads * sectors; 242 } else if (bb->partition_type == PARTITION_FORMAT_RISCIX) { 243 struct riscix_partition_table *rpt; 244 int loop; 245 246 /* 247 * We have a RISCiX partition table :-( groan 248 * 249 * Read the RISCiX partition table and see if 250 * there is a NetBSD partition 251 */ 252 253 bp->b_blkno = cyl * heads * sectors; 254 /* printf("Found RiscIX partition table @ %08x\n", 255 bp->b_blkno);*/ 256 bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; 257 bp->b_bcount = lp->d_secsize; 258 bp->b_oflags &= ~(BO_DONE); 259 bp->b_flags |= B_READ; 260 (*strat)(bp); 261 262 /* 263 * if successful, locate disk label within block 264 * and validate 265 */ 266 267 if (biowait(bp)) { 268 *msgp = "disk label I/O error"; 269 goto out; 270 } 271 272 rpt = (struct riscix_partition_table *)bp->b_data; 273 /* for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) 274 printf("p%d: %16s %08x %08x %08x\n", loop, 275 rpt->partitions[loop].rp_name, 276 rpt->partitions[loop].rp_start, 277 rpt->partitions[loop].rp_length, 278 rpt->partitions[loop].rp_type); 279 */ 280 for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { 281 if (strcmp(rpt->partitions[loop].rp_name, 282 "RiscBSD") == 0 || 283 strcmp(rpt->partitions[loop].rp_name, 284 "NetBSD") == 0 || 285 strcmp(rpt->partitions[loop].rp_name, 286 "Empty:") == 0) { 287 netbsdpartoff = 288 rpt->partitions[loop].rp_start; 289 break; 290 } 291 } 292 if (loop == NRISCIX_PARTITIONS) { 293 *msgp = "NetBSD partition identifier string not found."; 294 goto out; 295 } 296 } else { 297 *msgp = "Invalid partition format"; 298 goto out; 299 } 300 301 *cylp = cyl; 302 *netbsd_label_offp = netbsdpartoff; 303 *msgp = NULL; 304 out: 305 brelse(bp, 0); 306 return (rv); 307 } 308 309 310 int 311 filecore_label_locate(dev_t dev, 312 void (*strat)(struct buf *), 313 struct disklabel *lp, 314 struct cpu_disklabel *osdep, 315 int *cylp, int *netbsd_label_offp) 316 { 317 struct filecore_bootblock *bb; 318 int heads; 319 int sectors; 320 int rv; 321 int cyl, netbsdpartoff; 322 struct buf *bp; 323 324 /* get a buffer and initialize it */ 325 bp = geteblk((int)lp->d_secsize); 326 bp->b_dev = dev; 327 328 /* read the filecore boot block */ 329 330 /* printf("writedisklabel: Reading boot block\n");*/ 331 332 bp->b_blkno = FILECORE_BOOT_SECTOR; 333 bp->b_bcount = lp->d_secsize; 334 bp->b_flags |= B_READ; 335 bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; 336 (*strat)(bp); 337 338 /* 339 * if successful, validate boot block and locate 340 * partition table 341 */ 342 343 if ((rv = biowait(bp)) != 0) { 344 rv = -rv; 345 goto out; 346 } 347 348 bb = (struct filecore_bootblock *)bp->b_data; 349 rv = 1; 350 351 /* Validate boot block */ 352 353 if (bb->checksum != filecore_checksum((u_char *)bb)) { 354 /* 355 * Invalid boot block so lets assume the 356 * entire disc is NetBSD 357 */ 358 359 /* printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n");*/ 360 rv = 0; 361 goto out; 362 } 363 364 /* Do we have a NetBSD partition ? */ 365 366 if (bb->partition_type != PARTITION_FORMAT_RISCBSD) { 367 printf("writedisklabel: Invalid partition format\n"); 368 rv = -1; 369 goto out; 370 } 371 372 cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8); 373 374 heads = bb->heads; 375 sectors = bb->secspertrack; 376 377 /*printf("heads = %d nsectors = %d\n", heads, sectors);*/ 378 379 netbsdpartoff = cyl * heads * sectors; 380 381 *cylp = cyl; 382 *netbsd_label_offp = netbsdpartoff; 383 out: 384 brelse(bp, 0); 385 return (rv); 386 } 387