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