1 /* $NetBSD: disksubr.c,v 1.20 2002/03/27 20:23:11 wrstuden 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 36 */ 37 /*- 38 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, 39 * Michael L. Finch, Bradley A. Grantham, and 40 * Lawrence A. Kesteloot 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the Alice Group. 54 * 4. The names of the Alice Group or any of its members may not be used 55 * to endorse or promote products derived from this software without 56 * specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 61 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 67 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 68 * 69 */ 70 /* 71 * Copyright (C) 1996 Wolfgang Solfrank. 72 * Copyright (C) 1996 TooLs GmbH. 73 * All rights reserved. 74 * 75 * Redistribution and use in source and binary forms, with or without 76 * modification, are permitted provided that the following conditions 77 * are met: 78 * 1. Redistributions of source code must retain the above copyright 79 * notice, this list of conditions and the following disclaimer. 80 * 2. Redistributions in binary form must reproduce the above copyright 81 * notice, this list of conditions and the following disclaimer in the 82 * documentation and/or other materials provided with the distribution. 83 * 3. All advertising materials mentioning features or use of this software 84 * must display the following acknowledgement: 85 * This product includes software developed by TooLs GmbH. 86 * 4. The name of TooLs GmbH may not be used to endorse or promote products 87 * derived from this software without specific prior written permission. 88 * 89 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 90 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 91 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 92 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 93 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 94 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 95 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 96 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 97 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 98 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 99 */ 100 101 /* rewritten, 2-5-93 MLF */ 102 /* its alot cleaner now, and adding support for new partition types 103 * isn't a bitch anymore 104 * known bugs: 105 * 1) when only an HFS_PART part exists on a drive it gets assigned to "B" 106 * this is because of line 623 of sd.c, I think this line should go. 107 * 2) /sbin/disklabel expects the whole disk to be in "D", we put it in 108 * "C" (I think) and we don't set that position in the disklabel structure 109 * as used. Again, not my fault. 110 */ 111 #include <sys/param.h> 112 #include <sys/systm.h> 113 #include <sys/buf.h> 114 #include <sys/conf.h> 115 #include <sys/disk.h> 116 #include <sys/disklabel.h> 117 #include <sys/disklabel_mbr.h> 118 #include <sys/syslog.h> 119 120 #include <machine/bswap.h> 121 122 #define NUM_PARTS 32 123 124 #define ROOT_PART 1 125 #define UFS_PART 2 126 #define SWAP_PART 3 127 #define HFS_PART 4 128 #define SCRATCH_PART 5 129 130 int fat_types[] = { MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, 131 MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32, 132 MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L, 133 -1 }; 134 135 static int getFreeLabelEntry __P((struct disklabel *)); 136 static int whichType __P((struct part_map_entry *, u_int8_t *, int *)); 137 static void setpartition __P((struct part_map_entry *, 138 struct partition *, int)); 139 static int getNamedType __P((struct part_map_entry *, int, 140 struct disklabel *, int, int, int *)); 141 static char *read_mac_label __P((dev_t, void (*)(struct buf *), 142 struct disklabel *, struct cpu_disklabel *)); 143 static char *read_dos_label __P((dev_t, void (*)(struct buf *), 144 struct disklabel *, struct cpu_disklabel *)); 145 static int get_netbsd_label __P((dev_t dev, void (*strat)(struct buf *), 146 struct disklabel *lp, daddr_t bno)); 147 148 /* 149 * Find an entry in the disk label that is unused and return it 150 * or -1 if no entry 151 */ 152 static int 153 getFreeLabelEntry(lp) 154 struct disklabel *lp; 155 { 156 int i = 0; 157 158 for (i = 0; i < MAXPARTITIONS; i++) { 159 if ((i != RAW_PART) 160 && (lp->d_partitions[i].p_fstype == FS_UNUSED)) 161 return i; 162 } 163 164 return -1; 165 } 166 167 /* 168 * figure out what the type of the given part is and return it 169 */ 170 static int 171 whichType(struct part_map_entry *part, u_int8_t *fstype, int *clust) 172 { 173 struct blockzeroblock *bzb; 174 char typestr[32], *s; 175 int type; 176 177 /* Set default unix partition type. Certain partition types can 178 * specify a different partition type. */ 179 *fstype = FS_BSDFFS; 180 *clust = 0; /* only A/UX partitions not in cluster 0 */ 181 182 if (part->pmSig != PART_ENTRY_MAGIC || part->pmPartType[0] == '\0') 183 return 0; 184 185 strncpy(typestr, (char *)part->pmPartType, sizeof(typestr)); 186 typestr[sizeof(typestr) - 1] = '\0'; 187 for (s = typestr; *s; s++) 188 if ((*s >= 'a') && (*s <= 'z')) 189 *s = (*s - 'a' + 'A'); 190 191 if (strncmp(PART_TYPE_DRIVER, typestr, strlen(PART_TYPE_DRIVER)) == 0 || 192 strcmp(PART_TYPE_DRIVER43, typestr) == 0 || 193 strcmp(PART_TYPE_DRIVERATA, typestr) == 0 || 194 strcmp(PART_TYPE_DRIVERIOKIT, typestr) == 0 || 195 strcmp(PART_TYPE_FWDRIVER, typestr) == 0 || 196 strcmp(PART_TYPE_FWB_COMPONENT, typestr) == 0 || 197 strcmp(PART_TYPE_PARTMAP, typestr) == 0 || 198 strcmp(PART_TYPE_PATCHES, typestr) == 0) 199 type = 0; 200 else if (strcmp(PART_TYPE_NBSD_PPCBOOT, typestr) == 0) { 201 type = ROOT_PART; 202 bzb = (struct blockzeroblock *)(&part->pmBootArgs); 203 if ((bzb->bzbMagic == BZB_MAGIC) && 204 (bzb->bzbType < FSMAXTYPES)) 205 *fstype = bzb->bzbType; 206 } else if (strcmp(PART_TYPE_NETBSD, typestr) == 0 || 207 strcmp(PART_TYPE_NBSD_68KBOOT, typestr) == 0) { 208 type = UFS_PART; 209 bzb = (struct blockzeroblock *)(&part->pmBootArgs); 210 if ((bzb->bzbMagic == BZB_MAGIC) && 211 (bzb->bzbType < FSMAXTYPES)) 212 *fstype = bzb->bzbType; 213 } else if (strcmp(PART_TYPE_UNIX, typestr) == 0) { 214 /* unix part, swap, root, usr */ 215 bzb = (struct blockzeroblock *)(&part->pmBootArgs); 216 *clust = bzb->bzbCluster; 217 if (bzb->bzbMagic != BZB_MAGIC) 218 type = 0; 219 else if (bzb->bzbFlags & BZB_ROOTFS) 220 type = ROOT_PART; 221 else if (bzb->bzbFlags & (BZB_USRFS | BZB_USRFS_NEW)) 222 type = UFS_PART; 223 else if (bzb->bzbType == BZB_TYPESWAP) 224 type = SWAP_PART; 225 else 226 type = SCRATCH_PART; 227 } else if (strcmp(PART_TYPE_MAC, typestr) == 0) 228 type = HFS_PART; 229 else 230 type = SCRATCH_PART; /* no known type */ 231 232 return type; 233 } 234 235 static void 236 setpartition(struct part_map_entry *part, struct partition *pp, int fstype) 237 { 238 pp->p_size = part->pmPartBlkCnt; 239 pp->p_offset = part->pmPyPartStart; 240 pp->p_fstype = fstype; 241 242 part->pmPartType[0] = '\0'; 243 } 244 245 static int 246 getNamedType(part, num_parts, lp, type, alt, maxslot) 247 struct part_map_entry *part; 248 int num_parts; 249 struct disklabel *lp; 250 int type, alt; 251 int *maxslot; 252 { 253 struct blockzeroblock *bzb; 254 int i = 0, clust; 255 u_int8_t realtype; 256 257 for (i = 0; i < num_parts; i++) { 258 if (whichType(part + i, &realtype, &clust) != type) 259 continue; 260 261 if (type == ROOT_PART) { 262 bzb = (struct blockzeroblock *) 263 (&(part + i)->pmBootArgs); 264 if (alt >= 0 && alt != clust) 265 continue; 266 setpartition(part + i, &lp->d_partitions[0], realtype); 267 } else if (type == UFS_PART) { 268 bzb = (struct blockzeroblock *) 269 (&(part + i)->pmBootArgs); 270 if (alt >= 0 && alt != clust) 271 continue; 272 setpartition(part + i, &lp->d_partitions[6], realtype); 273 if (*maxslot < 6) 274 *maxslot = 6; 275 } else if (type == SWAP_PART) { 276 setpartition(part + i, &lp->d_partitions[1], FS_SWAP); 277 if (*maxslot < 1) 278 *maxslot = 1; 279 } else if (type == HFS_PART) { 280 setpartition(part + i, &lp->d_partitions[3], FS_HFS); 281 if (*maxslot < 3) 282 *maxslot = 3; 283 } else 284 printf("disksubr.c: can't do type %d\n", type); 285 286 return 0; 287 } 288 289 return -1; 290 } 291 292 /* 293 * MF -- 294 * here's what i'm gonna do: 295 * read in the entire diskpartition table, it may be bigger or smaller 296 * than NUM_PARTS but read that many entries. Each entry has a magic 297 * number so we'll know if an entry is crap. 298 * next fill in the disklabel with info like this 299 * next fill in the root, usr, and swap parts. 300 * then look for anything else and fit it in. 301 * A: root 302 * B: Swap 303 * C: Whole disk 304 * G: Usr 305 * 306 * 307 * I'm not entirely sure what netbsd386 wants in c & d 308 * 386bsd wants other stuff, so i'll leave them alone 309 * 310 * AKB -- I added to Mike's original algorithm by searching for a bzbCluster 311 * of zero for root, first. This allows A/UX to live on cluster 1 and 312 * NetBSD to live on cluster 0--regardless of the actual order on the 313 * disk. This whole algorithm should probably be changed in the future. 314 */ 315 static char * 316 read_mac_label(dev, strat, lp, osdep) 317 dev_t dev; 318 void (*strat)(struct buf *); 319 struct disklabel *lp; 320 struct cpu_disklabel *osdep; 321 { 322 struct part_map_entry *part; 323 struct partition *pp; 324 struct buf *bp; 325 char *msg = NULL; 326 int i, slot, maxslot = 0, clust; 327 u_int8_t realtype; 328 329 /* get buffer and initialize it */ 330 bp = geteblk((int)lp->d_secsize * NUM_PARTS); 331 bp->b_dev = dev; 332 333 /* read partition map */ 334 bp->b_blkno = 1; /* partition map starts at blk 1 */ 335 bp->b_bcount = lp->d_secsize * NUM_PARTS; 336 bp->b_flags |= B_READ; 337 bp->b_cylinder = 1 / lp->d_secpercyl; 338 (*strat)(bp); 339 340 if (biowait(bp)) { 341 msg = "Macintosh partition map I/O error"; 342 goto done; 343 } 344 345 part = (struct part_map_entry *)bp->b_data; 346 347 /* Fill in standard partitions */ 348 lp->d_npartitions = RAW_PART + 1; 349 if (getNamedType(part, NUM_PARTS, lp, ROOT_PART, 0, &maxslot)) 350 getNamedType(part, NUM_PARTS, lp, ROOT_PART, -1, &maxslot); 351 if (getNamedType(part, NUM_PARTS, lp, UFS_PART, 0, &maxslot)) 352 getNamedType(part, NUM_PARTS, lp, UFS_PART, -1, &maxslot); 353 getNamedType(part, NUM_PARTS, lp, SWAP_PART, -1, &maxslot); 354 getNamedType(part, NUM_PARTS, lp, HFS_PART, -1, &maxslot); 355 356 /* Now get as many of the rest of the partitions as we can */ 357 for (i = 0; i < NUM_PARTS; i++) { 358 slot = getFreeLabelEntry(lp); 359 if (slot < 0) 360 break; 361 362 pp = &lp->d_partitions[slot]; 363 364 switch (whichType(part + i, &realtype, &clust)) { 365 case ROOT_PART: 366 /* 367 * another root part will turn into a plain old 368 * UFS_PART partition, live with it. 369 */ 370 case UFS_PART: 371 setpartition(part + i, pp, realtype); 372 break; 373 case SWAP_PART: 374 setpartition(part + i, pp, FS_SWAP); 375 break; 376 case HFS_PART: 377 setpartition(part + i, pp, FS_HFS); 378 break; 379 case SCRATCH_PART: 380 setpartition(part + i, pp, FS_OTHER); 381 break; 382 default: 383 slot = 0; 384 break; 385 } 386 if (slot > maxslot) 387 maxslot = slot; 388 } 389 lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1; 390 391 done: 392 brelse(bp); 393 return msg; 394 } 395 396 /* Read MS-DOS partition table. 397 * 398 * XXX - 399 * Since FFS is endian sensitive, we pay no effort in attempting to 400 * dig up *BSD/i386 disk labels that may be present on the disk. 401 * Hence anything but DOS partitions is treated as unknown FS type, but 402 * this should suffice to mount_msdos Zip and other removable media. 403 */ 404 static char * 405 read_dos_label(dev, strat, lp, osdep) 406 dev_t dev; 407 void (*strat)(struct buf *); 408 struct disklabel *lp; 409 struct cpu_disklabel *osdep; 410 { 411 struct mbr_partition *dp; 412 struct partition *pp; 413 struct buf *bp; 414 char *msg = NULL; 415 int i, *ip, slot, maxslot = 0; 416 417 /* get a buffer and initialize it */ 418 bp = geteblk((int)lp->d_secsize); 419 bp->b_dev = dev; 420 421 /* read master boot record */ 422 bp->b_blkno = MBR_BBSECTOR; 423 bp->b_bcount = lp->d_secsize; 424 bp->b_flags |= B_READ; 425 bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl; 426 (*strat)(bp); 427 428 /* if successful, wander through dos partition table */ 429 if (biowait(bp)) { 430 msg = "dos partition I/O error"; 431 goto done; 432 } else { 433 /* XXX */ 434 dp = (struct mbr_partition *)(bp->b_data + MBR_PARTOFF); 435 for (i = 0; i < NMBRPART; i++, dp++) { 436 if (dp->mbrp_typ != 0) { 437 slot = getFreeLabelEntry(lp); 438 if (slot > maxslot) 439 maxslot = slot; 440 441 pp = &lp->d_partitions[slot]; 442 pp->p_fstype = FS_OTHER; 443 pp->p_offset = bswap32(dp->mbrp_start); 444 pp->p_size = bswap32(dp->mbrp_size); 445 446 for (ip = fat_types; *ip != -1; ip++) { 447 if (dp->mbrp_typ == *ip) { 448 pp->p_fstype = FS_MSDOS; 449 break; 450 } 451 } 452 } 453 } 454 } 455 lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1; 456 457 done: 458 brelse(bp); 459 return (msg); 460 } 461 462 /* 463 * Get real NetBSD disk label 464 */ 465 static int 466 get_netbsd_label(dev, strat, lp, bno) 467 dev_t dev; 468 void (*strat)(struct buf *); 469 struct disklabel *lp; 470 daddr_t bno; 471 { 472 struct buf *bp; 473 struct disklabel *dlp; 474 475 /* get a buffer and initialize it */ 476 bp = geteblk((int)lp->d_secsize); 477 bp->b_dev = dev; 478 479 /* Now get the label block */ 480 bp->b_blkno = bno + LABELSECTOR; 481 bp->b_bcount = lp->d_secsize; 482 bp->b_flags |= B_READ; 483 bp->b_cylinder = bp->b_blkno / (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl; 484 (*strat)(bp); 485 486 if (biowait(bp)) 487 goto done; 488 489 for (dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); 490 dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof (*dlp)); 491 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 492 if (dlp->d_magic == DISKMAGIC 493 && dlp->d_magic2 == DISKMAGIC 494 && dlp->d_npartitions <= MAXPARTITIONS 495 && dkcksum(dlp) == 0) { 496 *lp = *dlp; 497 brelse(bp); 498 return 1; 499 } 500 } 501 done: 502 brelse(bp); 503 return 0; 504 } 505 506 /* 507 * Attempt to read a disk label from a device using the indicated strategy 508 * routine. The label must be partly set up before this: secpercyl and 509 * anything required in the strategy routine (e.g., sector size) must be 510 * filled in before calling us. Returns null on success and an error 511 * string on failure. 512 * 513 * This will read sector zero. If this contains what looks like a valid 514 * Macintosh boot sector, we attempt to fill in the disklabel structure. 515 * If the first longword of the disk is a NetBSD disk label magic number, 516 * then we assume that it's a real disklabel and return it. 517 */ 518 char * 519 readdisklabel(dev, strat, lp, osdep) 520 dev_t dev; 521 void (*strat)(struct buf *); 522 struct disklabel *lp; 523 struct cpu_disklabel *osdep; 524 { 525 struct buf *bp; 526 char *msg = NULL; 527 528 if (lp->d_secperunit == 0) 529 lp->d_secperunit = 0x1fffffff; 530 531 if (lp->d_secpercyl == 0) { 532 return msg = "Zero secpercyl"; 533 } 534 bp = geteblk((int)lp->d_secsize); 535 536 bp->b_dev = dev; 537 bp->b_blkno = 0; 538 bp->b_resid = 0; 539 bp->b_bcount = lp->d_secsize; 540 bp->b_flags |= B_READ; 541 bp->b_cylinder = 1 / lp->d_secpercyl; 542 (*strat)(bp); 543 544 osdep->cd_start = -1; 545 546 if (biowait(bp)) 547 msg = "I/O error reading block zero"; 548 else if (get_netbsd_label(dev, strat, lp, 0)) 549 osdep->cd_start = 0; 550 else { 551 u_int16_t *sbSigp; 552 553 sbSigp = (u_int16_t *)bp->b_data; 554 if (*sbSigp == 0x4552) { 555 msg = read_mac_label(dev, strat, lp, osdep); 556 } else if (bswap16(*(u_int16_t *)(bp->b_data + MBR_MAGICOFF)) 557 == MBR_MAGIC) { 558 msg = read_dos_label(dev, strat, lp, osdep); 559 } else { 560 msg = "no disk label -- NetBSD or Macintosh"; 561 osdep->cd_start = 0; /* XXX for now */ 562 } 563 } 564 565 brelse(bp); 566 return (msg); 567 } 568 569 /* 570 * Check new disk label for sensibility before setting it. 571 */ 572 int 573 setdisklabel(olp, nlp, openmask, osdep) 574 struct disklabel *olp, *nlp; 575 u_long openmask; 576 struct cpu_disklabel *osdep; 577 { 578 /* sanity clause */ 579 if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 580 || (nlp->d_secsize % DEV_BSIZE) != 0) 581 return EINVAL; 582 583 /* special case to allow disklabel to be invalidated */ 584 if (nlp->d_magic == 0xffffffff) { 585 *olp = *nlp; 586 return 0; 587 } 588 589 if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC 590 || dkcksum(nlp) != 0) 591 return EINVAL; 592 593 /* openmask parameter ignored */ 594 595 *olp = *nlp; 596 return 0; 597 } 598 599 /* 600 * Write disk label back to device after modification. 601 */ 602 int 603 writedisklabel(dev, strat, lp, osdep) 604 dev_t dev; 605 void (*strat)(struct buf *); 606 struct disklabel *lp; 607 struct cpu_disklabel *osdep; 608 { 609 struct buf *bp; 610 int error; 611 struct disklabel label; 612 613 /* 614 * Try to re-read a disklabel, in case he changed the MBR. 615 */ 616 label = *lp; 617 readdisklabel(dev, strat, &label, osdep); 618 if (osdep->cd_start < 0) 619 return EINVAL; 620 621 /* get a buffer and initialize it */ 622 bp = geteblk(lp->d_secsize); 623 bp->b_dev = dev; 624 625 bp->b_blkno = osdep->cd_start + LABELSECTOR; 626 bp->b_cylinder = bp->b_blkno / (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl; 627 bp->b_bcount = lp->d_secsize; 628 629 bp->b_flags |= B_READ; 630 (*strat)(bp); 631 error = biowait(bp); 632 if (error != 0) 633 goto done; 634 635 bp->b_flags &= ~(B_READ|B_DONE); 636 bp->b_flags |= B_WRITE; 637 638 memcpy((caddr_t)bp->b_data + LABELOFFSET, (caddr_t)lp, sizeof *lp); 639 640 (*strat)(bp); 641 error = biowait(bp); 642 643 done: 644 brelse(bp); 645 646 return error; 647 } 648 649 /* 650 * Determine the size of the transfer, and make sure it is 651 * within the boundaris of the partition. Adjust transfer 652 * if needed, and signal errors or early completion. 653 */ 654 int 655 bounds_check_with_label(bp, lp, wlabel) 656 struct buf *bp; 657 struct disklabel *lp; 658 int wlabel; 659 { 660 struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); 661 int sz; 662 663 sz = howmany(bp->b_bcount, lp->d_secsize); 664 665 if (bp->b_blkno + sz > p->p_size) { 666 sz = p->p_size - bp->b_blkno; 667 if (sz == 0) { 668 /* If axactly at end of disk, return EOF. */ 669 bp->b_resid = bp->b_bcount; 670 goto done; 671 } 672 if (sz < 0) { 673 /* If past end of disk, return EINVAL. */ 674 bp->b_error = EINVAL; 675 goto bad; 676 } 677 /* Otherwise truncate request. */ 678 bp->b_bcount = sz * lp->d_secsize; 679 } 680 681 /* calculate cylinder for disksort to order transfers with */ 682 bp->b_cylinder = (bp->b_blkno + p->p_offset) 683 / (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl; 684 685 return 1; 686 687 bad: 688 bp->b_flags |= B_ERROR; 689 done: 690 return 0; 691 } 692