disksubr_acorn.c revision 1.12
1/* $NetBSD: disksubr_acorn.c,v 1.12 2013/03/09 16:02:25 christos 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.12 2013/03/09 16:02:25 christos Exp $"); 101 102#include <sys/param.h> 103#include <sys/systm.h> 104#include <sys/buf.h> 105#include <sys/disklabel.h> 106 107static 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 */ 141static int 142filecore_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 178int 179filecore_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 @ %08x\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", loop, 281 __func__, 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; 310out: 311 brelse(bp, 0); 312 return (rv); 313} 314 315 316/* 317 * Return -1 not found, 0 found positive errno 318 */ 319int 320filecore_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; 399out: 400 brelse(bp, 0); 401 return (rv); 402} 403