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
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
filecore_checksum(u_char * bootblock)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
filecore_label_read(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * osdep,const char ** msgp,int * cylp,int * netbsd_label_offp)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 @ %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;
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
filecore_label_locate(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * osdep,int * cylp,int * netbsd_label_offp)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