1 /*-
2 * Copyright (c) 1994 Bruce D. Evans.
3 * All rights reserved.
4 *
5 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
37 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
38 * $FreeBSD: releng/5.0/sys/pc98/pc98/diskslice_machdep.c 104272 2002-10-01 07:24:55Z phk $
39 */
40
41 /*
42 * PC9801 port by KATO Takenor <kato@eclogite.eps.nagoya-u.ac.jp>
43 */
44
45 #include "compat_atdisk.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/bio.h>
50 #include <sys/buf.h>
51 #include <sys/conf.h>
52 #include <sys/disk.h>
53 #include <sys/disklabel.h>
54 #ifndef PC98
55 #define DOSPTYP_EXTENDED 5
56 #define DOSPTYP_EXTENDEDX 15
57 #define DOSPTYP_ONTRACK 84
58 #endif
59 #if defined(PC98) && !defined(PC98_ATCOMPAT)
60 #include <sys/diskpc98.h>
61 #else
62 #include <sys/diskmbr.h>
63 #endif
64 #include <sys/diskslice.h>
65 #include <sys/malloc.h>
66 #include <sys/syslog.h>
67
68 #define TRACE(str) do { if (dsi_debug) printf str; } while (0)
69
70 static volatile u_char dsi_debug;
71
72 #ifndef PC98
73 static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
74 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
75 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
76 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
77 { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
78 };
79 #endif
80
81 static int check_part(char *sname, struct dos_partition *dp,
82 u_long offset, int nsectors, int ntracks,
83 u_long mbr_offset);
84 #ifndef PC98
85 static void mbr_extended(dev_t dev, struct disklabel *lp,
86 struct diskslices *ssp, u_long ext_offset,
87 u_long ext_size, u_long base_ext_offset,
88 int nsectors, int ntracks, u_long mbr_offset,
89 int level);
90 #endif
91 static int mbr_setslice(char *sname, struct disklabel *lp,
92 struct diskslice *sp, struct dos_partition *dp,
93 u_long br_offset);
94
95 #ifdef PC98
96 #define DPBLKNO(cyl,hd,sect) ((cyl)*(lp->d_secpercyl))
97 #if NCOMPAT_ATDISK > 0
98 int atcompat_dsinit(dev_t dev,
99 struct disklabel *lp, struct diskslices **sspp);
100 #endif
101 #endif
102
103 static int
104 check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
105 char *sname;
106 struct dos_partition *dp;
107 u_long offset;
108 int nsectors;
109 int ntracks;
110 u_long mbr_offset;
111 {
112 int chs_ecyl;
113 int chs_esect;
114 int chs_scyl;
115 int chs_ssect;
116 int error;
117 u_long esector;
118 u_long esector1;
119 u_long secpercyl;
120 u_long ssector;
121 u_long ssector1;
122 #ifdef PC98
123 u_long pc98_start;
124 u_long pc98_size;
125 #endif
126
127 secpercyl = (u_long)nsectors * ntracks;
128 #ifdef PC98
129 chs_scyl = dp->dp_scyl;
130 chs_ssect = dp->dp_ssect;
131 ssector = chs_ssect + dp->dp_shd * nsectors +
132 chs_scyl * secpercyl + mbr_offset;
133 #else
134 chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
135 chs_ssect = DPSECT(dp->dp_ssect);
136 ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl
137 + mbr_offset;
138 #endif
139 #ifdef PC98
140 pc98_start = dp->dp_scyl * secpercyl;
141 pc98_size = dp->dp_ecyl ?
142 (dp->dp_ecyl + 1) * secpercyl - pc98_start : 0;
143 ssector1 = offset + pc98_start;
144 #else
145 ssector1 = offset + dp->dp_start;
146 #endif
147
148 /*
149 * If ssector1 is on a cylinder >= 1024, then ssector can't be right.
150 * Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
151 * apart from the cylinder being reduced modulo 1024. Always allow
152 * 1023/255/63.
153 */
154 if ((ssector < ssector1
155 && ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
156 && chs_scyl == 1023)
157 || (secpercyl != 0
158 && (ssector1 - ssector) % (1024 * secpercyl) == 0)))
159 || (dp->dp_scyl == 255 && dp->dp_shd == 255
160 && dp->dp_ssect == 255)) {
161 TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
162 sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
163 ssector = ssector1;
164 }
165
166 #ifdef PC98
167 chs_ecyl = dp->dp_ecyl;
168 chs_esect = nsectors - 1;
169 esector = chs_esect + (ntracks - 1) * nsectors +
170 chs_ecyl * secpercyl + mbr_offset;
171 esector1 = ssector1 + pc98_size - 1;
172 #else
173 chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect);
174 chs_esect = DPSECT(dp->dp_esect);
175 esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl
176 + mbr_offset;
177 esector1 = ssector1 + dp->dp_size - 1;
178 #endif
179
180 /* Allow certain bogus C/H/S values for esector, as above. */
181 if ((esector < esector1
182 && ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
183 && chs_ecyl == 1023)
184 || (secpercyl != 0
185 && (esector1 - esector) % (1024 * secpercyl) == 0)))
186 || (dp->dp_ecyl == 255 && dp->dp_ehd == 255
187 && dp->dp_esect == 255)) {
188 TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
189 sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
190 esector = esector1;
191 }
192
193 error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
194 if (bootverbose)
195 #ifdef PC98
196 printf("%s: mid 0x%x, start %lu, end = %lu, size %lu%s\n",
197 sname, dp->dp_mid, ssector1, esector1, pc98_size,
198 error ? "" : ": OK");
199 #else
200 printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n",
201 sname, dp->dp_typ, ssector1, esector1,
202 (u_long)dp->dp_size, error ? "" : ": OK");
203 #endif
204 if (ssector != ssector1 && bootverbose)
205 printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
206 sname, chs_scyl, dp->dp_shd, chs_ssect,
207 ssector, ssector1);
208 if (esector != esector1 && bootverbose)
209 printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
210 sname, chs_ecyl, dp->dp_ehd, chs_esect,
211 esector, esector1);
212 return (error);
213 }
214
215 int
216 dsinit(dev, lp, sspp)
217 dev_t dev;
218 struct disklabel *lp;
219 struct diskslices **sspp;
220 {
221 struct buf *bp;
222 u_char *cp;
223 int dospart;
224 struct dos_partition *dp;
225 struct dos_partition *dp0;
226 int error;
227 int max_ncyls;
228 int max_nsectors;
229 int max_ntracks;
230 u_long mbr_offset;
231 char partname[2];
232 u_long secpercyl;
233 char *sname;
234 struct diskslice *sp;
235 struct diskslices *ssp;
236
237 mbr_offset = DOSBBSECTOR;
238 #ifdef PC98
239 /* Read master boot record. */
240 if ((int)lp->d_secsize < 1024)
241 bp = geteblk((int)1024);
242 else
243 bp = geteblk((int)lp->d_secsize);
244 #else
245 reread_mbr:
246 /* Read master boot record. */
247 bp = geteblk((int)lp->d_secsize);
248 #endif
249 bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
250 bp->b_blkno = mbr_offset;
251 bp->b_bcount = lp->d_secsize;
252 bp->b_iocmd = BIO_READ;
253 #ifdef PC98
254 if (bp->b_bcount < 1024)
255 bp->b_bcount = 1024;
256 #endif
257 DEV_STRATEGY(bp, 1);
258 if (bufwait(bp) != 0) {
259 disk_err(&bp->b_io, "reading primary partition table: error",
260 0, 1);
261 error = EIO;
262 goto done;
263 }
264
265 /* Weakly verify it. */
266 cp = bp->b_data;
267 sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
268 if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
269 if (bootverbose)
270 printf("%s: invalid primary partition table: no magic\n",
271 sname);
272 error = EINVAL;
273 goto done;
274 }
275 #ifdef PC98
276 /*
277 * entire disk for FreeBSD
278 */
279 if ((*(cp + 512) == 0x57) && (*(cp + 513) == 0x45) &&
280 (*(cp + 514) == 0x56) && (*(cp + 515) == 0x82)) {
281 sname = dsname(dev, dkunit(dev), BASE_SLICE,
282 RAW_PART, partname);
283 free(*sspp, M_DEVBUF);
284 ssp = dsmakeslicestruct(MAX_SLICES, lp);
285 *sspp = ssp;
286
287 /* Initialize normal slices. */
288 sp = &ssp->dss_slices[BASE_SLICE];
289 sp->ds_offset = 0;
290 sp->ds_size = lp->d_secperunit;
291 sp->ds_type = DOSPTYP_386BSD;
292 sp->ds_subtype = 0xc4;
293 error = 0;
294 ssp->dss_nslices = BASE_SLICE + 1;
295 goto done;
296 }
297
298 /*
299 * XXX --- MS-DOG MO
300 */
301 if ((*(cp + 0x0e) == 1) && (*(cp + 0x15) == 0xf0) &&
302 (*(cp + 0x1c) == 0x0) &&
303 ((*(cp + 512) == 0xf0) || (*(cp + 512) == 0xf8)) &&
304 (*(cp + 513) == 0xff) && (*(cp + 514) == 0xff)) {
305 sname = dsname(dev, dkunit(dev), BASE_SLICE,
306 RAW_PART, partname);
307 free(*sspp, M_DEVBUF);
308 ssp = dsmakeslicestruct(MAX_SLICES, lp);
309 *sspp = ssp;
310
311 /* Initialize normal slices. */
312 sp = &ssp->dss_slices[BASE_SLICE];
313 sp->ds_offset = 0;
314 sp->ds_size = lp->d_secperunit;
315 sp->ds_type = 0xa0; /* XXX */
316 sp->ds_subtype = 0x81; /* XXX */
317 error = 0;
318 ssp->dss_nslices = BASE_SLICE + 1;
319 goto done;
320 }
321 #if NCOMPAT_ATDISK > 0
322 /*
323 * Check magic number of 'extended format' for PC-9801.
324 * If no magic, it may be formatted on IBM-PC.
325 */
326 if (((cp[4] != 'I') || (cp[5] != 'P') || (cp[6] != 'L') ||
327 (cp[7] != '1')) &&
328 ((strncmp(devtoname(bp->b_dev), "da", 2) == 0) ||
329 (strncmp(devtoname(bp->b_dev), "wd", 2) == 0) ||
330 (strncmp(devtoname(bp->b_dev), "ad", 2) == 0))) {
331 /* IBM-PC HDD */
332 bp->b_flags |= B_INVAL | B_AGE;
333 brelse(bp);
334 return atcompat_dsinit(dev, lp, sspp);
335 }
336 #endif
337 dp0 = (struct dos_partition *)(cp + 512);
338 #else
339 dp0 = (struct dos_partition *)(cp + DOSPARTOFF);
340
341 /* Check for "Ontrack Diskmanager". */
342 for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
343 if (dp->dp_typ == DOSPTYP_ONTRACK) {
344 if (bootverbose)
345 printf(
346 "%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
347 bp->b_flags |= B_INVAL | B_AGE;
348 brelse(bp);
349 mbr_offset = 63;
350 goto reread_mbr;
351 }
352 }
353
354 if (bcmp(dp0, historical_bogus_partition_table,
355 sizeof historical_bogus_partition_table) == 0) {
356 TRACE(("%s: invalid primary partition table: historical\n",
357 sname));
358 error = EINVAL;
359 goto done;
360 }
361 #endif
362
363 /* Guess the geometry. */
364 /*
365 * TODO:
366 * Perhaps skip entries with 0 size.
367 * Perhaps only look at entries of type DOSPTYP_386BSD.
368 */
369 max_ncyls = 0;
370 max_nsectors = 0;
371 max_ntracks = 0;
372 for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
373 int ncyls;
374 int nsectors;
375 int ntracks;
376
377
378 #ifdef PC98
379 ncyls = lp->d_ncylinders;
380 #else
381 ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
382 #endif
383 if (max_ncyls < ncyls)
384 max_ncyls = ncyls;
385 #ifdef PC98
386 nsectors = lp->d_nsectors;
387 #else
388 nsectors = DPSECT(dp->dp_esect);
389 #endif
390 if (max_nsectors < nsectors)
391 max_nsectors = nsectors;
392 #ifdef PC98
393 ntracks = lp->d_ntracks;
394 #else
395 ntracks = dp->dp_ehd + 1;
396 #endif
397 if (max_ntracks < ntracks)
398 max_ntracks = ntracks;
399 }
400
401 /*
402 * Check that we have guessed the geometry right by checking the
403 * partition entries.
404 */
405 /*
406 * TODO:
407 * As above.
408 * Check for overlaps.
409 * Check against d_secperunit if the latter is reliable.
410 */
411 error = 0;
412 #ifdef PC98
413 for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
414 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0)
415 continue;
416 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
417 RAW_PART, partname);
418 #else
419 for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
420 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
421 && dp->dp_start == 0 && dp->dp_size == 0)
422 continue;
423 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
424 RAW_PART, partname);
425 #endif
426 /*
427 * Temporarily ignore errors from this check. We could
428 * simplify things by accepting the table eariler if we
429 * always ignore errors here. Perhaps we should always
430 * accept the table if the magic is right but not let
431 * bad entries affect the geometry.
432 */
433 check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
434 mbr_offset);
435 }
436 if (error != 0)
437 goto done;
438
439 /*
440 * Accept the DOS partition table.
441 * First adjust the label (we have been careful not to change it
442 * before we can guarantee success).
443 */
444 secpercyl = (u_long)max_nsectors * max_ntracks;
445 if (secpercyl != 0) {
446 lp->d_nsectors = max_nsectors;
447 lp->d_ntracks = max_ntracks;
448 lp->d_secpercyl = secpercyl;
449 lp->d_ncylinders = lp->d_secperunit / secpercyl;
450 }
451
452 /*
453 * We are passed a pointer to a suitably initialized minimal
454 * slices "struct" with no dangling pointers in it. Replace it
455 * by a maximal one. This usually oversizes the "struct", but
456 * enlarging it while searching for logical drives would be
457 * inconvenient.
458 */
459 free(*sspp, M_DEVBUF);
460 ssp = dsmakeslicestruct(MAX_SLICES, lp);
461 *sspp = ssp;
462
463 /* Initialize normal slices. */
464 sp = &ssp->dss_slices[BASE_SLICE];
465 for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
466 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
467 RAW_PART, partname);
468 (void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
469 }
470 ssp->dss_nslices = BASE_SLICE + NDOSPART;
471
472 #ifndef PC98
473 /* Handle extended partitions. */
474 sp -= NDOSPART;
475 for (dospart = 0; dospart < NDOSPART; dospart++, sp++)
476 if (sp->ds_type == DOSPTYP_EXTENDED ||
477 sp->ds_type == DOSPTYP_EXTENDEDX)
478 mbr_extended(bp->b_dev, lp, ssp,
479 sp->ds_offset, sp->ds_size, sp->ds_offset,
480 max_nsectors, max_ntracks, mbr_offset, 1);
481
482 /*
483 * mbr_extended() abuses ssp->dss_nslices for the number of slices
484 * that would be found if there were no limit on the number of slices
485 * in *ssp. Cut it back now.
486 */
487 if (ssp->dss_nslices > MAX_SLICES)
488 ssp->dss_nslices = MAX_SLICES;
489 #endif
490
491 done:
492 bp->b_flags |= B_INVAL | B_AGE;
493 brelse(bp);
494 if (error == EINVAL)
495 error = 0;
496 return (error);
497 }
498
499 #ifndef PC98
500 void
501 mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
502 ntracks, mbr_offset, level)
503 dev_t dev;
504 struct disklabel *lp;
505 struct diskslices *ssp;
506 u_long ext_offset;
507 u_long ext_size;
508 u_long base_ext_offset;
509 int nsectors;
510 int ntracks;
511 u_long mbr_offset;
512 int level;
513 {
514 struct buf *bp;
515 u_char *cp;
516 int dospart;
517 struct dos_partition *dp;
518 struct dos_partition dpcopy[NDOSPART];
519 u_long ext_offsets[NDOSPART];
520 u_long ext_sizes[NDOSPART];
521 char partname[2];
522 int slice;
523 char *sname;
524 struct diskslice *sp;
525
526 if (level >= 16) {
527 printf(
528 "%s: excessive recursion in search for slices; aborting search\n",
529 devtoname(dev));
530 return;
531 }
532
533 /* Read extended boot record. */
534 bp = geteblk((int)lp->d_secsize);
535 bp->b_dev = dev;
536 bp->b_blkno = ext_offset;
537 bp->b_bcount = lp->d_secsize;
538 bp->b_iocmd = BIO_READ;
539 DEV_STRATEGY(bp, 1);
540 if (bufwait(bp) != 0) {
541 disk_err(&bp->b_io, "reading extended partition table: error",
542 0, 1);
543 goto done;
544 }
545
546 /* Weakly verify it. */
547 cp = bp->b_data;
548 if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
549 sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART,
550 partname);
551 if (bootverbose)
552 printf("%s: invalid extended partition table: no magic\n",
553 sname);
554 goto done;
555 }
556
557 /* Make a copy of the partition table to avoid alignment problems. */
558 memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
559
560 slice = ssp->dss_nslices;
561 for (dospart = 0, dp = &dpcopy[0]; dospart < NDOSPART;
562 dospart++, dp++) {
563 ext_sizes[dospart] = 0;
564 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
565 && dp->dp_start == 0 && dp->dp_size == 0)
566 continue;
567 if (dp->dp_typ == DOSPTYP_EXTENDED ||
568 dp->dp_typ == DOSPTYP_EXTENDEDX) {
569 static char buf[32];
570
571 sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
572 RAW_PART, partname);
573 snprintf(buf, sizeof(buf), "%s", sname);
574 if (strlen(buf) < sizeof buf - 11)
575 strcat(buf, "<extended>");
576 check_part(buf, dp, base_ext_offset, nsectors,
577 ntracks, mbr_offset);
578 ext_offsets[dospart] = base_ext_offset + dp->dp_start;
579 ext_sizes[dospart] = dp->dp_size;
580 } else {
581 sname = dsname(dev, dkunit(dev), slice, RAW_PART,
582 partname);
583 check_part(sname, dp, ext_offset, nsectors, ntracks,
584 mbr_offset);
585 if (slice >= MAX_SLICES) {
586 printf("%s: too many slices\n", sname);
587 slice++;
588 continue;
589 }
590 sp = &ssp->dss_slices[slice];
591 if (mbr_setslice(sname, lp, sp, dp, ext_offset) != 0)
592 continue;
593 slice++;
594 }
595 }
596 ssp->dss_nslices = slice;
597
598 /* If we found any more slices, recursively find all the subslices. */
599 for (dospart = 0; dospart < NDOSPART; dospart++)
600 if (ext_sizes[dospart] != 0)
601 mbr_extended(dev, lp, ssp, ext_offsets[dospart],
602 ext_sizes[dospart], base_ext_offset,
603 nsectors, ntracks, mbr_offset, ++level);
604
605 done:
606 bp->b_flags |= B_INVAL | B_AGE;
607 brelse(bp);
608 }
609 #endif
610
611 static int
612 mbr_setslice(sname, lp, sp, dp, br_offset)
613 char *sname;
614 struct disklabel *lp;
615 struct diskslice *sp;
616 struct dos_partition *dp;
617 u_long br_offset;
618 {
619 u_long offset;
620 u_long size;
621
622 #ifdef PC98
623 offset = DPBLKNO(dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
624 size = dp->dp_ecyl ?
625 DPBLKNO(dp->dp_ecyl + 1, dp->dp_ehd, dp->dp_esect) - offset : 0;
626 #else
627 offset = br_offset + dp->dp_start;
628 if (offset > lp->d_secperunit || offset < br_offset) {
629 printf(
630 "%s: slice starts beyond end of the disk: rejecting it\n",
631 sname);
632 return (1);
633 }
634 size = lp->d_secperunit - offset;
635 if (size >= dp->dp_size)
636 size = dp->dp_size;
637 else
638 printf(
639 "%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n",
640 sname, (u_long)dp->dp_size, size);
641 #endif
642 sp->ds_offset = offset;
643 sp->ds_size = size;
644 #ifdef PC98
645 sp->ds_type = dp->dp_mid;
646 sp->ds_subtype = dp->dp_sid;
647 strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name));
648 #else
649 sp->ds_type = dp->dp_typ;
650 #ifdef PC98_ATCOMPAT
651 /* Fake FreeBSD(98). */
652 if (sp->ds_type == DOSPTYP_386BSD)
653 sp->ds_type = 0x94;
654 #endif
655 #endif /* PC98 */
656 #if 0
657 lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
658 #endif
659 return (0);
660 }
661
662 #ifdef __alpha__
663 void
664 alpha_fix_srm_checksum(bp)
665 struct buf *bp;
666 {
667 u_int64_t *p;
668 u_int64_t sum;
669 int i;
670
671 p = (u_int64_t *) bp->b_data;
672 sum = 0;
673 for (i = 0; i < 63; i++)
674 sum += p[i];
675 p[63] = sum;
676 }
677 #endif
Cache object: 83b9dbf62983d935195c53cd74639e75
|