1 /* $NetBSD: disksubr.c,v 1.32 2024/06/02 19:20:09 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.32 2024/06/02 19:20:09 andvar Exp $"); 36 37 #include "opt_mbr.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/buf.h> 42 #include <sys/disklabel.h> 43 #include <sys/disk.h> 44 #include <sys/syslog.h> 45 46 #include <sys/bswap.h> 47 48 int fat_types[] = { MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, 49 MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32, 50 MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L, 51 -1 }; 52 53 #define NO_MBR_SIGNATURE ((struct mbr_partition *) -1) 54 55 #ifdef BSDDISKLABEL_EI 56 void swap_endian_disklabel(struct disklabel *, struct disklabel *); 57 uint16_t dkcksum_re(struct disklabel *); 58 #endif 59 #ifdef COMPAT_MMEYE_OLDLABEL 60 void swap_mmeye_disklabel(struct disklabel *, struct disklabel *); 61 uint16_t dkcksum_mmeye(struct disklabel *); 62 #endif 63 64 static struct mbr_partition *mbr_findslice(struct mbr_partition *, 65 struct buf *); 66 67 #ifdef BSDDISKLABEL_EI 68 void 69 swap_endian_disklabel(struct disklabel *nlp, struct disklabel *olp) 70 { 71 int i; 72 #define SW16(X) nlp->X = bswap16(olp->X) 73 #define SW32(X) nlp->X = bswap32(olp->X) 74 75 SW32(d_magic); 76 SW16(d_type); 77 SW16(d_subtype); 78 79 /* no need to swap char strings */ 80 memcpy(nlp->d_typename, olp->d_typename, sizeof(nlp->d_typename)); 81 82 /* XXX What should we do for d_un (an union of char and pointers) ? */ 83 memcpy(nlp->d_packname, olp->d_packname, sizeof(nlp->d_packname)); 84 85 SW32(d_secsize); 86 SW32(d_nsectors); 87 SW32(d_ntracks); 88 SW32(d_ncylinders); 89 SW32(d_secpercyl); 90 SW32(d_secperunit); 91 92 SW16(d_sparespertrack); 93 SW16(d_sparespercyl); 94 95 SW32(d_acylinders); 96 97 SW16(d_rpm); 98 SW16(d_interleave); 99 SW16(d_trackskew); /* sector 0 skew, per track */ 100 SW16(d_cylskew); /* sector 0 skew, per cylinder */ 101 SW32(d_headswitch); /* head switch time, usec */ 102 SW32(d_trkseek); /* track-to-track seek, usec */ 103 SW32(d_flags); /* generic flags */ 104 105 for (i = 0; i < NDDATA; i++) 106 SW32(d_drivedata[i]); /* drive-type specific information */ 107 108 for (i = 0; i < NSPARE; i++) 109 SW32(d_spare[i]); /* reserved for future use */ 110 111 SW32(d_magic2); /* the magic number (again) */ 112 SW16(d_checksum); /* xor of data incl. partitions */ 113 114 /* filesystem and partition information: */ 115 SW16(d_npartitions); /* number of partitions in following */ 116 SW32(d_bbsize); /* size of boot area at sn0, bytes */ 117 SW32(d_sbsize); /* max size of fs superblock, bytes */ 118 119 for (i = 0; i < MAXPARTITIONS; i++) { 120 SW32(d_partitions[i].p_size); 121 SW32(d_partitions[i].p_offset); 122 SW32(d_partitions[i].p_fsize); 123 /* p_fstype and p_frag is uint8_t, so no need to swap */ 124 nlp->d_partitions[i].p_fstype = olp->d_partitions[i].p_fstype; 125 nlp->d_partitions[i].p_frag = olp->d_partitions[i].p_frag; 126 SW16(d_partitions[i].p_cpg); 127 } 128 #undef SW32 129 #undef SW16 130 } 131 132 uint16_t 133 dkcksum_re(struct disklabel *lp) 134 { 135 uint16_t *start, *end; 136 uint16_t sum = 0; 137 138 start = (uint16_t *)lp; 139 end = (uint16_t *)&lp->d_partitions[bswap16(lp->d_npartitions)]; 140 while (start < end) 141 sum ^= *start++; 142 return (sum); 143 } 144 #endif 145 146 #ifdef COMPAT_MMEYE_OLDLABEL 147 void 148 swap_mmeye_disklabel(struct disklabel *nlp, struct disklabel *olp) 149 { 150 int i; 151 uint16_t *np, *op; 152 153 #if BYTE_ORDER == BIG_ENDIAN 154 #define SW16(X) nlp->X = bswap16(olp->X) 155 #define SW32(X) nlp->X = bswap32(olp->X) 156 #else 157 #define SW16(X) nlp->X = olp->X 158 #define SW32(X) nlp->X = olp->X 159 #endif 160 161 SW32(d_magic); 162 SW16(d_type); 163 SW16(d_subtype); 164 165 op = (uint16_t *)&olp->d_typename[0]; 166 np = (uint16_t *)&nlp->d_typename[0]; 167 for (i = 0; i < sizeof(olp->d_typename) / sizeof(uint16_t); i++) 168 *np++ = bswap16(*op++); 169 170 op = (uint16_t *)&olp->d_un.un_d_packname[0]; 171 np = (uint16_t *)&nlp->d_un.un_d_packname[0]; 172 for (i = 0; i < sizeof(olp->d_un) / sizeof(uint16_t); i++) 173 *np++ = bswap16(*op++); 174 175 SW32(d_secsize); 176 SW32(d_nsectors); 177 SW32(d_ntracks); 178 SW32(d_ncylinders); 179 SW32(d_secpercyl); 180 SW32(d_secperunit); 181 182 SW16(d_sparespertrack); 183 SW16(d_sparespercyl); 184 185 SW32(d_acylinders); 186 187 SW16(d_rpm); 188 SW16(d_interleave); 189 SW16(d_trackskew); /* sector 0 skew, per track */ 190 SW16(d_cylskew); /* sector 0 skew, per cylinder */ 191 SW32(d_headswitch); /* head switch time, usec */ 192 SW32(d_trkseek); /* track-to-track seek, usec */ 193 SW32(d_flags); /* generic flags */ 194 195 for (i = 0; i < NDDATA; i++) 196 SW32(d_drivedata[i]); /* drive-type specific information */ 197 198 for (i = 0; i < NSPARE; i++) 199 SW32(d_spare[i]); /* reserved for future use */ 200 201 SW32(d_magic2); /* the magic number (again) */ 202 SW16(d_checksum); /* xor of data incl. partitions */ 203 204 /* filesystem and partition information: */ 205 SW16(d_npartitions); /* number of partitions in following */ 206 SW32(d_bbsize); /* size of boot area at sn0, bytes */ 207 SW32(d_sbsize); /* max size of fs superblock, bytes */ 208 209 for (i = 0; i < MAXPARTITIONS; i++) { 210 SW32(d_partitions[i].p_size); 211 SW32(d_partitions[i].p_offset); 212 SW32(d_partitions[i].p_fsize); 213 nlp->d_partitions[i].p_fstype = olp->d_partitions[i].p_fstype; 214 nlp->d_partitions[i].p_frag = olp->d_partitions[i].p_frag; 215 SW16(d_partitions[i].p_cpg); 216 } 217 #undef SW32 218 #undef SW16 219 } 220 221 uint16_t 222 dkcksum_mmeye(struct disklabel *lp) 223 { 224 struct disklabel tdl; 225 int i, offset; 226 uint16_t *start, *end, *fstype; 227 uint16_t sum = 0; 228 229 tdl = *lp; 230 231 for (i = 0; i < MAXPARTITIONS; i++) { 232 fstype = (uint16_t *)&tdl.d_partitions[i].p_fstype; 233 *fstype = bswap16(*fstype); 234 } 235 236 offset = offsetof(struct disklabel, 237 d_partitions[le16toh(lp->d_npartitions)]); 238 start = (uint16_t *)&tdl; 239 end = start + offset; 240 241 while (start < end) 242 sum ^= *start++; 243 244 #ifdef COMPAT_MMEYE_OLDLABEL_BROKEN 245 if (sum != 0 && 246 tdl.d_checksum == 0) { 247 printf("disklabel: mmeye oldlabel broken found\n"); 248 sum = 0; /* XXXX */ 249 } 250 #endif 251 252 return (sum); 253 } 254 #endif 255 256 /* 257 * Scan MBR for NetBSD partition. Return NO_MBR_SIGNATURE if no MBR found 258 * Otherwise, copy valid MBR partition-table into dp, and if a NetBSD 259 * partition is found, return a pointer to it; else return NULL. 260 */ 261 static struct mbr_partition * 262 mbr_findslice(struct mbr_partition *dp, struct buf *bp) 263 { 264 struct mbr_partition *ourdp = NULL; 265 uint16_t *mbrmagicp; 266 int i; 267 268 /* Note: Magic number is little-endian. */ 269 mbrmagicp = (uint16_t *)((char *)bp->b_data + MBR_MAGIC_OFFSET); 270 if (le16toh(*mbrmagicp) != MBR_MAGIC) 271 return (NO_MBR_SIGNATURE); 272 273 /* XXX how do we check veracity/bounds of this? */ 274 memcpy(dp, (char *)bp->b_data + MBR_PART_OFFSET, 275 MBR_PART_COUNT * sizeof(*dp)); 276 277 /* look for NetBSD partition */ 278 for (i = 0; i < MBR_PART_COUNT; i++) { 279 if (dp[i].mbrp_type == MBR_PTYPE_NETBSD) { 280 ourdp = &dp[i]; 281 break; 282 } 283 } 284 285 return (ourdp); 286 } 287 288 289 /* 290 * Attempt to read a disk label from a device 291 * using the indicated strategy routine. 292 * The label must be partly set up before this: 293 * secpercyl, secsize and anything required for a block i/o read 294 * operation in the driver's strategy/start routines 295 * must be filled in before calling us. 296 * 297 * If dos partition table requested, attempt to load it and 298 * find disklabel inside a DOS partition. Also, if bad block 299 * table needed, attempt to extract it as well. Return buffer 300 * for use in signalling errors if requested. 301 * 302 * Returns null on success and an error string on failure. 303 */ 304 const char * 305 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, 306 struct cpu_disklabel *osdep) 307 { 308 struct mbr_partition *dp; 309 struct partition *pp; 310 struct dkbad *bdp; 311 struct buf *bp; 312 struct disklabel *dlp; 313 const char *msg = NULL; 314 int dospartoff, cyl, i, *ip; 315 316 /* minimal requirements for archtypal disk label */ 317 if (lp->d_secsize == 0) 318 lp->d_secsize = DEV_BSIZE; 319 if (lp->d_secperunit == 0) 320 lp->d_secperunit = 0x1fffffff; 321 #if 0 322 if (lp->d_ncylinders == 16383) { 323 printf("disklabel: Disk > 8G ... readjusting chs %d/%d/%d to ", 324 lp->d_ncylinders, lp->d_ntracks, lp->d_nsectors); 325 lp->d_ncylinders = lp->d_secperunit / lp->d_ntracks / lp->d_nsectors; 326 printf("%d/%d/%d\n", 327 lp->d_ncylinders, lp->d_ntracks, lp->d_nsectors); 328 } 329 #endif 330 lp->d_npartitions = RAW_PART + 1; 331 for (i = 0; i < RAW_PART; i++) { 332 lp->d_partitions[i].p_size = 0; 333 lp->d_partitions[i].p_offset = 0; 334 } 335 if (lp->d_partitions[i].p_size == 0) 336 lp->d_partitions[i].p_size = 0x1fffffff; 337 lp->d_partitions[i].p_offset = 0; 338 339 /* get a buffer and initialize it */ 340 bp = geteblk((int)lp->d_secsize); 341 bp->b_dev = dev; 342 343 /* do dos partitions in the process of getting disklabel? */ 344 dospartoff = 0; 345 cyl = LABELSECTOR / lp->d_secpercyl; 346 if (!osdep) 347 goto nombrpart; 348 dp = osdep->mbrparts; 349 350 /* read master boot record */ 351 bp->b_blkno = MBR_BBSECTOR; 352 bp->b_bcount = lp->d_secsize; 353 bp->b_flags |= B_READ; 354 bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl; 355 (*strat)(bp); 356 357 /* if successful, wander through dos partition table */ 358 if (biowait(bp)) { 359 msg = "dos partition I/O error"; 360 goto done; 361 } else { 362 struct mbr_partition *ourdp = NULL; 363 364 ourdp = mbr_findslice(dp, bp); 365 if (ourdp == NO_MBR_SIGNATURE) 366 goto nombrpart; 367 368 for (i = 0; i < MBR_PART_COUNT; i++, dp++) { 369 /* Install in partition e, f, g, or h. */ 370 pp = &lp->d_partitions[RAW_PART + 1 + i]; 371 pp->p_offset = le32toh(dp->mbrp_start); 372 pp->p_size = le32toh(dp->mbrp_size); 373 for (ip = fat_types; *ip != -1; ip++) { 374 if (dp->mbrp_type == *ip) 375 pp->p_fstype = FS_MSDOS; 376 } 377 if (dp->mbrp_type == MBR_PTYPE_LNXEXT2) 378 pp->p_fstype = FS_EX2FS; 379 380 if (dp->mbrp_type == MBR_PTYPE_NTFS) 381 pp->p_fstype = FS_NTFS; 382 383 /* is this ours? */ 384 if (dp == ourdp) { 385 /* need sector address for SCSI/IDE, 386 cylinder for ESDI/ST506/RLL */ 387 dospartoff = le32toh(dp->mbrp_start); 388 cyl = MBR_PCYL(dp->mbrp_scyl, dp->mbrp_ssect); 389 390 /* update disklabel with details */ 391 lp->d_partitions[2].p_size = 392 le32toh(dp->mbrp_size); 393 lp->d_partitions[2].p_offset = 394 le32toh(dp->mbrp_start); 395 #if 0 396 if (lp->d_ntracks != dp->mbrp_ehd + 1 || 397 lp->d_nsectors != MBR_PSECT(dp->mbrp_esect)) { 398 printf("disklabel: BIOS sees chs %d/%d/%d as ", 399 lp->d_ncylinders, lp->d_ntracks, 400 lp->d_nsectors); 401 lp->d_ntracks = dp->mbrp_ehd + 1; 402 lp->d_nsectors = MBR_PSECT(dp->mbrp_esect); 403 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 404 lp->d_ncylinders = lp->d_secperunit / lp->d_secpercyl; 405 if (! lp->d_ncylinders) 406 lp->d_ncylinders = 1; 407 printf("%d/%d/%d\n", 408 lp->d_ncylinders, lp->d_ntracks, 409 lp->d_nsectors); 410 } 411 #endif 412 } 413 } 414 lp->d_npartitions = RAW_PART + 1 + i; 415 } 416 417 nombrpart: 418 /* next, dig out disk label */ 419 bp->b_blkno = dospartoff + LABELSECTOR; 420 bp->b_cylinder = cyl; 421 bp->b_bcount = lp->d_secsize; 422 bp->b_oflags &= ~(BO_DONE); 423 bp->b_flags |= B_READ; 424 (*strat)(bp); 425 426 /* if successful, locate disk label within block and validate */ 427 if (biowait(bp)) { 428 msg = "disk label I/O error"; 429 goto done; 430 } 431 for (dlp = (struct disklabel *)bp->b_data; 432 dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize - 433 sizeof(*dlp)); 434 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 435 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) { 436 /* disklabel is written in host's endian */ 437 if (dlp->d_npartitions > MAXPARTITIONS || 438 dkcksum(dlp) != 0) 439 msg = "disk label corrupted"; 440 else { 441 *lp = *dlp; 442 msg = NULL; 443 break; 444 } 445 } 446 #ifdef BSDDISKLABEL_EI 447 if (bswap32(dlp->d_magic) == DISKMAGIC && 448 bswap32(dlp->d_magic2) == DISKMAGIC) { 449 /* disklabel is written in reversed endian */ 450 if (bswap16(dlp->d_npartitions) > MAXPARTITIONS || 451 dkcksum_re(dlp) != 0) 452 msg = "disk label corrupted"; 453 else { 454 swap_endian_disklabel(lp, dlp); 455 /* recalculate cksum in host's endian */ 456 lp->d_checksum = 0; 457 lp->d_checksum = dkcksum(lp); 458 459 msg = NULL; 460 break; 461 } 462 } 463 #endif 464 #ifdef COMPAT_MMEYE_OLDLABEL 465 if (le32toh(dlp->d_magic) == DISKMAGIC && 466 le32toh(dlp->d_magic2) == DISKMAGIC) { 467 if (le16toh(dlp->d_npartitions) > MAXPARTITIONS || 468 dkcksum_mmeye(dlp) != 0) 469 msg = "disk label corrupted"; 470 else { 471 /* disklabel is written in old mmeye's way */ 472 swap_mmeye_disklabel(lp, dlp); 473 /* recalculate cksum in host's endian */ 474 lp->d_checksum = 0; 475 lp->d_checksum = dkcksum(lp); 476 477 msg = NULL; 478 break; 479 } 480 } 481 #endif 482 if (msg == NULL) 483 msg = "no disk label"; 484 } 485 486 if (msg) 487 goto done; 488 489 /* obtain bad sector table if requested and present */ 490 if (osdep && (lp->d_flags & D_BADSECT)) { 491 struct dkbad *db; 492 493 bdp = &osdep->bad; 494 i = 0; 495 do { 496 /* read a bad sector table */ 497 bp->b_oflags &= ~(BO_DONE); 498 bp->b_flags |= B_READ; 499 bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i; 500 if (lp->d_secsize > DEV_BSIZE) 501 bp->b_blkno *= lp->d_secsize / DEV_BSIZE; 502 else 503 bp->b_blkno /= DEV_BSIZE / lp->d_secsize; 504 bp->b_bcount = lp->d_secsize; 505 bp->b_cylinder = lp->d_ncylinders - 1; 506 (*strat)(bp); 507 508 /* if successful, validate, otherwise try another */ 509 if (biowait(bp)) { 510 msg = "bad sector table I/O error"; 511 } else { 512 db = (struct dkbad *)(bp->b_data); 513 #define DKBAD_MAGIC 0x4321 514 if (db->bt_mbz == 0 515 && db->bt_flag == DKBAD_MAGIC) { 516 msg = NULL; 517 *bdp = *db; 518 break; 519 } else 520 msg = "bad sector table corrupted"; 521 } 522 } while (bp->b_error != 0 && (i += 2) < 10 && 523 i < lp->d_nsectors); 524 } 525 526 done: 527 brelse(bp, 0); 528 return (msg); 529 } 530 531 /* 532 * Write disk label back to device after modification. 533 */ 534 int 535 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, 536 struct cpu_disklabel *osdep) 537 { 538 struct mbr_partition *dp; 539 struct buf *bp; 540 struct disklabel *dlp; 541 int error, dospartoff, cyl; 542 543 /* get a buffer and initialize it */ 544 bp = geteblk((int)lp->d_secsize); 545 bp->b_dev = dev; 546 547 /* do dos partitions in the process of getting disklabel? */ 548 dospartoff = 0; 549 cyl = LABELSECTOR / lp->d_secpercyl; 550 if (!osdep) 551 goto nombrpart; 552 dp = osdep->mbrparts; 553 554 /* read master boot record */ 555 bp->b_blkno = MBR_BBSECTOR; 556 bp->b_bcount = lp->d_secsize; 557 bp->b_flags |= B_READ; 558 bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl; 559 (*strat)(bp); 560 561 if ((error = biowait(bp)) == 0) { 562 struct mbr_partition *ourdp = NULL; 563 564 ourdp = mbr_findslice(dp, bp); 565 if (ourdp == NO_MBR_SIGNATURE) 566 goto nombrpart; 567 568 if (ourdp) { 569 /* need sector address for SCSI/IDE, 570 cylinder for ESDI/ST506/RLL */ 571 dospartoff = le32toh(ourdp->mbrp_start); 572 cyl = MBR_PCYL(ourdp->mbrp_scyl, ourdp->mbrp_ssect); 573 } 574 } 575 576 nombrpart: 577 #ifdef maybe 578 /* disklabel in appropriate location? */ 579 if (lp->d_partitions[2].p_offset != 0 580 && lp->d_partitions[2].p_offset != dospartoff) { 581 error = EXDEV; 582 goto done; 583 } 584 #endif 585 586 /* next, dig out disk label */ 587 bp->b_blkno = dospartoff + LABELSECTOR; 588 bp->b_cylinder = cyl; 589 bp->b_bcount = lp->d_secsize; 590 bp->b_oflags &= ~(BO_DONE); 591 bp->b_flags |= B_READ; 592 (*strat)(bp); 593 594 /* if successful, locate disk label within block and validate */ 595 if ((error = biowait(bp)) != 0) 596 goto done; 597 for (dlp = (struct disklabel *)bp->b_data; 598 dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize - 599 sizeof(*dlp)); 600 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 601 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 602 dlp->d_npartitions <= MAXPARTITIONS && 603 dkcksum(dlp) == 0) { 604 /* found disklabel in host's endian */ 605 *dlp = *lp; 606 goto found; 607 #ifdef BSDDISKLABEL_EI 608 } else if (bswap32(dlp->d_magic) == DISKMAGIC && 609 bswap32(dlp->d_magic2) == DISKMAGIC && 610 bswap16(dlp->d_npartitions) <= MAXPARTITIONS && 611 dkcksum_re(dlp) == 0) { 612 /* found disklabel in the opposite endian */ 613 swap_endian_disklabel(dlp, lp); 614 /* recalculate cksum in reversed endian */ 615 dlp->d_checksum = 0; 616 dlp->d_checksum = dkcksum_re(dlp); 617 goto found; 618 #endif 619 #ifdef COMPAT_MMEYE_OLDLABEL 620 } else if (le32toh(dlp->d_magic) == DISKMAGIC && 621 le32toh(dlp->d_magic2) == DISKMAGIC && 622 le16toh(dlp->d_npartitions) <= MAXPARTITIONS && 623 dkcksum_mmeye(dlp) == 0) { 624 /* found disklabel by old mmeye's rule */ 625 swap_mmeye_disklabel(dlp, lp); 626 /* recalculate cksum for it */ 627 dlp->d_checksum = 0; 628 dlp->d_checksum = dkcksum_mmeye(dlp); 629 goto found; 630 #endif 631 } 632 } 633 /* No valid disklabel found on disk */ 634 error = ESRCH; 635 goto done; 636 637 found: 638 bp->b_oflags &= ~(BO_DONE); 639 bp->b_flags &= ~(B_READ); 640 bp->b_flags |= B_WRITE; 641 (*strat)(bp); 642 error = biowait(bp); 643 644 done: 645 brelse(bp, 0); 646 return (error); 647 } 648