1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * 27 * Portions of this source code were provided by International 28 * Computers Limited (ICL) under a development agreement with AT&T. 29 */ 30 31 /* 32 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 33 * Use is subject to license terms. 34 */ 35 36 /* 37 * Sun Microsystems version of fmthard: 38 * 39 * Supports the following arguments: 40 * 41 * -i Writes VTOC to stdout, rather than disk 42 * -q Quick check: exit code 0 if VTOC ok 43 * -d <data> Incremental changes to the VTOC 44 * -n <vname> Change volume name to <vname> 45 * -s <file> Read VTOC information from <file>, or stdin ("-") 46 * -u <state> Reboot after writing VTOC, according to <state>: 47 * boot: AD_BOOT (standard reboot) 48 * firm: AD_IBOOT (interactive reboot) 49 * 50 * Note that fmthard cannot write a VTOC on an unlabeled disk. 51 * You must use format or SunInstall for this purpose. 52 * (NOTE: the above restriction only applies on Sparc systems). 53 * 54 * The primary motivation for fmthard is to duplicate the 55 * partitioning from disk to disk: 56 * 57 * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 58 */ 59 60 #include <stdio.h> 61 #include <fcntl.h> 62 #include <errno.h> 63 #include <string.h> 64 #include <stdlib.h> 65 #include <unistd.h> 66 #include <sys/types.h> 67 #include <sys/param.h> 68 #include <sys/int_limits.h> 69 #include <sys/stat.h> 70 #include <sys/uadmin.h> 71 #include <sys/open.h> 72 #include <sys/vtoc.h> 73 #include <sys/dkio.h> 74 #include <sys/isa_defs.h> 75 #include <sys/efi_partition.h> 76 77 #if defined(_SUNOS_VTOC_16) 78 #include <sys/dklabel.h> 79 #endif 80 81 #include <sys/sysmacros.h> 82 83 #ifndef SECSIZE 84 #define SECSIZE DEV_BSIZE 85 #endif /* SECSIZE */ 86 87 /* 88 * Internal functions. 89 */ 90 extern int main(int, char **); 91 static void display(struct dk_geom *, struct extvtoc *, char *); 92 static void display64(struct dk_gpt *, char *); 93 static void insert(char *, struct extvtoc *); 94 static void insert64(char *, struct dk_gpt *); 95 static void load(FILE *, struct dk_geom *, struct extvtoc *); 96 static void load64(FILE *, int fd, struct dk_gpt **); 97 static void usage(void); 98 static void validate(struct dk_geom *, struct extvtoc *); 99 static void validate64(struct dk_gpt *); 100 static int vread(int, struct extvtoc *, char *); 101 static void vread64(int, struct dk_gpt **, char *); 102 static void vwrite(int, struct extvtoc *, char *); 103 static void vwrite64(int, struct dk_gpt *, char *); 104 105 /* 106 * Static variables. 107 */ 108 static char *delta; /* Incremental update */ 109 static short eflag; /* force write of an EFI label */ 110 static short iflag; /* Prints VTOC w/o updating */ 111 static short qflag; /* Check for a formatted disk */ 112 static short uflag; /* Exit to firmware after writing */ 113 /* new vtoc and reboot. Used during */ 114 /* installation of core floppies */ 115 static diskaddr_t lastlba = 0; /* last LBA on 64-bit VTOC */ 116 117 #if defined(sparc) 118 static char *uboot = "boot"; 119 120 #elif defined(i386) 121 /* use installgrub(1M) to install boot blocks */ 122 static char *uboot = ""; 123 #else 124 #error No platform defined. 125 #endif /* various platform-specific definitions */ 126 127 static char *ufirm = "firm"; 128 static int sectsiz; 129 #if defined(_SUNOS_VTOC_16) 130 static struct extvtoc disk_vtoc; 131 #endif /* defined(_SUNOS_VTOC_16) */ 132 133 int 134 main(int argc, char **argv) 135 { 136 int fd; 137 int c; 138 char *dfile; 139 char *vname; 140 struct stat statbuf; 141 #if defined(_SUNOS_VTOC_8) 142 struct extvtoc disk_vtoc; 143 #endif /* defined(_SUNOS_VTOC_8) */ 144 struct dk_gpt *disk_efi; 145 struct dk_geom disk_geom; 146 struct dk_minfo minfo; 147 int n; 148 149 150 disk_efi = NULL; 151 dfile = NULL; 152 vname = NULL; 153 #if defined(sparc) 154 while ((c = getopt(argc, argv, "ed:u:in:qs:")) != EOF) 155 156 #elif defined(i386) 157 while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF) 158 159 #else 160 #error No platform defined. 161 #endif 162 switch (c) { 163 #if defined(i386) 164 case 'p': 165 case 'b': 166 (void) fprintf(stderr, 167 "fmthard: -p and -b no longer supported." 168 " Use installgrub(1M) to install boot blocks\n"); 169 break; 170 #endif /* defined(i386) */ 171 172 case 'd': 173 delta = optarg; 174 break; 175 case 'e': 176 ++eflag; 177 break; 178 case 'i': 179 ++iflag; 180 break; 181 case 'n': 182 vname = optarg; 183 break; 184 case 'q': 185 ++qflag; 186 break; 187 case 's': 188 dfile = optarg; 189 break; 190 case 'u': 191 if (strcmp(uboot, optarg) == 0) 192 ++uflag; 193 else if (strcmp(ufirm, optarg) == 0) 194 uflag = 2; 195 196 break; 197 default: 198 usage(); 199 } 200 201 202 if (argc - optind != 1) 203 usage(); 204 205 if (stat(argv[optind], (struct stat *)&statbuf) == -1) { 206 (void) fprintf(stderr, 207 "fmthard: Cannot stat device %s\n", 208 argv[optind]); 209 exit(1); 210 } 211 212 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { 213 (void) fprintf(stderr, 214 "fmthard: %s must be a raw device.\n", 215 argv[optind]); 216 exit(1); 217 } 218 219 if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) { 220 (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n", 221 argv[optind], strerror(errno)); 222 exit(1); 223 } 224 225 if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == 0) { 226 sectsiz = minfo.dki_lbsize; 227 } 228 229 if (sectsiz == 0) { 230 sectsiz = SECSIZE; 231 } 232 233 /* 234 * Get the geometry information for this disk from the driver 235 */ 236 if (!eflag && ioctl(fd, DKIOCGGEOM, &disk_geom)) { 237 #ifdef DEBUG 238 perror("DKIOCGGEOM failed"); 239 #endif /* DEBUG */ 240 if (errno == ENOTSUP) { 241 /* disk has EFI labels */ 242 eflag++; 243 } else { 244 (void) fprintf(stderr, 245 "%s: Cannot get disk geometry\n", argv[optind]); 246 (void) close(fd); 247 exit(1); 248 } 249 } 250 251 /* 252 * Read the vtoc on the disk 253 */ 254 if (!eflag) { 255 if (vread(fd, &disk_vtoc, argv[optind]) == 1) 256 eflag++; 257 } 258 if (eflag && ((dfile == NULL) || qflag)) { 259 vread64(fd, &disk_efi, argv[optind]); 260 } 261 262 /* 263 * Quick check for valid disk: 0 if ok, 1 if not 264 */ 265 if (qflag) { 266 (void) close(fd); 267 if (!eflag) { 268 exit(disk_vtoc.v_sanity == VTOC_SANE ? 0 : 1); 269 } else { 270 exit(disk_efi->efi_version <= EFI_VERSION102 ? 0 : 1); 271 } 272 } 273 274 /* 275 * Incremental changes to the VTOC 276 */ 277 if (delta) { 278 if (!eflag) { 279 insert(delta, &disk_vtoc); 280 validate(&disk_geom, &disk_vtoc); 281 vwrite(fd, &disk_vtoc, argv[optind]); 282 } else { 283 insert64(delta, disk_efi); 284 validate64(disk_efi); 285 vwrite64(fd, disk_efi, argv[optind]); 286 } 287 (void) close(fd); 288 exit(0); 289 } 290 291 if (!dfile && !vname) 292 usage(); 293 294 /* 295 * Read new VTOC from stdin or data file 296 */ 297 if (dfile) { 298 if (strcmp(dfile, "-") == 0) { 299 if (!eflag) 300 load(stdin, &disk_geom, &disk_vtoc); 301 else 302 load64(stdin, fd, &disk_efi); 303 } else { 304 FILE *fp; 305 if ((fp = fopen(dfile, "r")) == NULL) { 306 (void) fprintf(stderr, "Cannot open file %s\n", 307 dfile); 308 (void) close(fd); 309 exit(1); 310 } 311 if (!eflag) 312 load(fp, &disk_geom, &disk_vtoc); 313 else 314 load64(fp, fd, &disk_efi); 315 (void) fclose(fp); 316 } 317 } 318 319 /* 320 * Print the modified VTOC, rather than updating the disk 321 */ 322 if (iflag) { 323 if (!eflag) 324 display(&disk_geom, &disk_vtoc, argv[optind]); 325 else 326 display64(disk_efi, argv[optind]); 327 (void) close(fd); 328 exit(0); 329 } 330 331 if (vname) { 332 n = MIN(strlen(vname) + 1, LEN_DKL_VVOL); 333 if (!eflag) { 334 (void) memcpy(disk_vtoc.v_volume, vname, n); 335 } else { 336 for (c = 0; c < disk_efi->efi_nparts; c++) { 337 if (disk_efi->efi_parts[c].p_tag == 338 V_RESERVED) { 339 (void) memcpy(&disk_efi->efi_parts[c].p_name, 340 vname, n); 341 } 342 } 343 } 344 345 } 346 /* 347 * Write the new VTOC on the disk 348 */ 349 if (!eflag) { 350 validate(&disk_geom, &disk_vtoc); 351 vwrite(fd, &disk_vtoc, argv[optind]); 352 } else { 353 validate64(disk_efi); 354 vwrite64(fd, disk_efi, argv[optind]); 355 } 356 357 /* 358 * Shut system down after writing a new vtoc to disk 359 * This is used during installation of core floppies. 360 */ 361 if (uflag == 1) 362 (void) uadmin(A_REBOOT, AD_BOOT, 0); 363 else if (uflag == 2) 364 (void) uadmin(A_REBOOT, AD_IBOOT, 0); 365 366 (void) printf("fmthard: New volume table of contents now in place.\n"); 367 368 return (0); 369 } 370 371 372 373 /* 374 * display () 375 * 376 * display contents of VTOC without writing it to disk 377 */ 378 static void 379 display(struct dk_geom *geom, struct extvtoc *vtoc, char *device) 380 { 381 int i; 382 int c; 383 384 /* 385 * Print out the VTOC 386 */ 387 (void) printf("* %s default partition map\n", device); 388 if (*vtoc->v_volume) { 389 (void) printf("* Volume Name: "); 390 for (i = 0; i < LEN_DKL_VVOL; i++) { 391 if ((c = vtoc->v_volume[i]) == 0) 392 break; 393 (void) printf("%c", c); 394 } 395 (void) printf("\n"); 396 } 397 (void) printf("*\n"); 398 (void) printf("* Dimensions:\n"); 399 (void) printf("* %d bytes/sector\n", sectsiz); 400 (void) printf("* %d sectors/track\n", geom->dkg_nsect); 401 (void) printf("* %d tracks/cylinder\n", geom->dkg_nhead); 402 (void) printf("* %d cylinders\n", geom->dkg_pcyl); 403 (void) printf("* %d accessible cylinders\n", geom->dkg_ncyl); 404 (void) printf("*\n"); 405 (void) printf("* Flags:\n"); 406 (void) printf("* 1: unmountable\n"); 407 (void) printf("* 10: read-only\n"); 408 (void) printf("*\n"); 409 (void) printf( 410 "\n* Partition Tag Flag First Sector Sector Count\n"); 411 for (i = 0; i < V_NUMPAR; i++) { 412 if (vtoc->v_part[i].p_size > 0) 413 (void) printf( 414 " %d %d 0%x %llu %llu\n", 415 i, vtoc->v_part[i].p_tag, 416 vtoc->v_part[i].p_flag, 417 vtoc->v_part[i].p_start, 418 vtoc->v_part[i].p_size); 419 } 420 exit(0); 421 } 422 423 /* 424 * display64 () 425 * 426 * display64 contents of EFI partition without writing it to disk 427 */ 428 static void 429 display64(struct dk_gpt *efi, char *device) 430 { 431 int i; 432 433 /* 434 * Print out the VTOC 435 */ 436 (void) printf("* %s default partition map\n", device); 437 (void) printf("*\n"); 438 (void) printf("* Dimensions:\n"); 439 (void) printf("* %d bytes/sector\n", efi->efi_lbasize); 440 (void) printf("* N/A sectors/track\n"); 441 (void) printf("* N/A tracks/cylinder\n"); 442 (void) printf("* N/A cylinders\n"); 443 (void) printf("* N/A accessible cylinders\n"); 444 (void) printf("*\n"); 445 (void) printf("* Flags:\n"); 446 (void) printf("* 1: unmountable\n"); 447 (void) printf("* 10: read-only\n"); 448 (void) printf("*\n"); 449 (void) printf( 450 "\n* Partition Tag Flag First Sector Sector Count\n"); 451 for (i = 0; i < efi->efi_nparts; i++) { 452 if (efi->efi_parts[i].p_size > 0) 453 (void) printf( 454 " %d %d 0%x %8lld %8lld\n", 455 i, efi->efi_parts[i].p_tag, 456 efi->efi_parts[i].p_flag, 457 efi->efi_parts[i].p_start, 458 efi->efi_parts[i].p_size); 459 } 460 exit(0); 461 } 462 463 464 /* 465 * insert() 466 * 467 * Insert a change into the VTOC. 468 */ 469 static void 470 insert(char *data, struct extvtoc *vtoc) 471 { 472 int part; 473 int tag; 474 uint_t flag; 475 diskaddr_t start; 476 uint64_t size; 477 478 if (sscanf(data, "%d:%d:%x:%llu:%llu", 479 &part, &tag, &flag, &start, &size) != 5) { 480 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 481 exit(1); 482 } 483 if (part >= V_NUMPAR) { 484 (void) fprintf(stderr, 485 "Error in data \"%s\": No such partition %x\n", 486 data, part); 487 exit(1); 488 } 489 vtoc->v_part[part].p_tag = (ushort_t)tag; 490 vtoc->v_part[part].p_flag = (ushort_t)flag; 491 vtoc->v_part[part].p_start = start; 492 vtoc->v_part[part].p_size = size; 493 } 494 495 /* 496 * insert64() 497 * 498 * Insert a change into the VTOC. 499 */ 500 static void 501 insert64(char *data, struct dk_gpt *efi) 502 { 503 int part; 504 int tag; 505 uint_t flag; 506 diskaddr_t start; 507 diskaddr_t size; 508 509 if (sscanf(data, "%d:%d:%x:%lld:%lld", 510 &part, &tag, &flag, &start, &size) != 5) { 511 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 512 exit(1); 513 } 514 if (part >= efi->efi_nparts) { 515 (void) fprintf(stderr, 516 "Error in data \"%s\": No such partition %x\n", 517 data, part); 518 exit(1); 519 } 520 efi->efi_parts[part].p_tag = (ushort_t)tag; 521 efi->efi_parts[part].p_flag = (ushort_t)flag; 522 efi->efi_parts[part].p_start = start; 523 efi->efi_parts[part].p_size = size; 524 } 525 526 /* 527 * load() 528 * 529 * Load VTOC information from a datafile. 530 */ 531 static void 532 load(FILE *fp, struct dk_geom *geom, struct extvtoc *vtoc) 533 { 534 int part; 535 int tag; 536 uint_t flag; 537 diskaddr_t start; 538 uint64_t size; 539 char line[256]; 540 int i; 541 uint64_t nblks; 542 uint64_t fullsz; 543 544 for (i = 0; i < V_NUMPAR; ++i) { 545 vtoc->v_part[i].p_tag = 0; 546 vtoc->v_part[i].p_flag = V_UNMNT; 547 vtoc->v_part[i].p_start = 0; 548 vtoc->v_part[i].p_size = 0; 549 } 550 /* 551 * initialize partition 2, by convention it corresponds to whole 552 * disk. It will be overwritten, if specified in the input datafile 553 */ 554 fullsz = (uint64_t)geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 555 vtoc->v_part[2].p_tag = V_BACKUP; 556 vtoc->v_part[2].p_flag = V_UNMNT; 557 vtoc->v_part[2].p_start = 0; 558 vtoc->v_part[2].p_size = fullsz; 559 560 nblks = geom->dkg_nsect * geom->dkg_nhead; 561 562 while (fgets(line, sizeof (line) - 1, fp)) { 563 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 564 continue; 565 line[strlen(line) - 1] = '\0'; 566 if (sscanf(line, "%d %d %x %llu %llu", 567 &part, &tag, &flag, &start, &size) != 5) { 568 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 569 line); 570 exit(1); 571 } 572 if (part >= V_NUMPAR) { 573 (void) fprintf(stderr, 574 "No such partition %x: \"%s\"\n", 575 part, line); 576 exit(1); 577 } 578 if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) { 579 (void) fprintf(stderr, 580 "Partition %d not aligned on cylinder boundary: \"%s\"\n", 581 part, line); 582 exit(1); 583 } 584 vtoc->v_part[part].p_tag = (ushort_t)tag; 585 vtoc->v_part[part].p_flag = (ushort_t)flag; 586 vtoc->v_part[part].p_start = start; 587 vtoc->v_part[part].p_size = size; 588 } 589 for (part = 0; part < V_NUMPAR; part++) { 590 vtoc->timestamp[part] = (time_t)0; 591 } 592 } 593 594 /* 595 * load64() 596 * 597 * Load VTOC information from a datafile. 598 */ 599 static void 600 load64(FILE *fp, int fd, struct dk_gpt **efi) 601 { 602 int part; 603 int tag; 604 uint_t flag; 605 diskaddr_t start; 606 diskaddr_t size; 607 int nlines = 0; 608 char line[256]; 609 int i; 610 uint_t max_part = 0; 611 char **mem = NULL; 612 613 while (fgets(line, sizeof (line) - 1, fp)) { 614 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 615 continue; 616 line[strlen(line) - 1] = '\0'; 617 if (sscanf(line, "%d %d %x %lld %lld", 618 &part, &tag, &flag, &start, &size) != 5) { 619 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 620 line); 621 exit(1); 622 } 623 mem = realloc(mem, sizeof (*mem) * (nlines + 1)); 624 if (mem == NULL) { 625 (void) fprintf(stderr, "realloc failed\n"); 626 exit(1); 627 } 628 mem[nlines] = strdup(line); 629 if (mem[nlines] == NULL) { 630 (void) fprintf(stderr, "strdup failed\n"); 631 exit(1); 632 } 633 nlines++; 634 if (part > max_part) 635 max_part = part; 636 } 637 max_part++; 638 639 if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) { 640 (void) fprintf(stderr, 641 "efi_alloc_and_init failed: %d\n", i); 642 exit(1); 643 } 644 for (i = 0; i < (*efi)->efi_nparts; ++i) { 645 (*efi)->efi_parts[i].p_tag = V_UNASSIGNED; 646 (*efi)->efi_parts[i].p_flag = V_UNMNT; 647 (*efi)->efi_parts[i].p_start = 0; 648 (*efi)->efi_parts[i].p_size = 0; 649 } 650 lastlba = (*efi)->efi_last_u_lba; 651 652 for (i = 0; i < nlines; i++) { 653 if (sscanf(mem[i], "%d %d %x %lld %lld", 654 &part, &tag, &flag, &start, &size) != 5) { 655 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 656 line); 657 exit(1); 658 } 659 free(mem[i]); 660 if (part >= (*efi)->efi_nparts) { 661 (void) fprintf(stderr, 662 "No such partition %x: \"%s\"\n", 663 part, line); 664 exit(1); 665 } 666 (*efi)->efi_parts[part].p_tag = (ushort_t)tag; 667 (*efi)->efi_parts[part].p_flag = (ushort_t)flag; 668 (*efi)->efi_parts[part].p_start = start; 669 (*efi)->efi_parts[part].p_size = size; 670 } 671 (*efi)->efi_nparts = max_part; 672 free(mem); 673 } 674 675 676 static void 677 usage() 678 { 679 #if defined(sparc) 680 (void) fprintf(stderr, 681 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ 682 raw-device\n"); 683 684 #elif defined(i386) 685 (void) fprintf(stderr, 686 "Usage: fmthard [ -i ] [ -S ] [-I geom_file] \ 687 -n volumename | -s datafile [ -d arguments] raw-device\n"); 688 689 #else 690 #error No platform defined. 691 #endif 692 exit(2); 693 } 694 695 /* 696 * validate() 697 * 698 * Validate the new VTOC. 699 */ 700 static void 701 validate(struct dk_geom *geom, struct extvtoc *vtoc) 702 { 703 int i; 704 int j; 705 uint64_t fullsz; 706 diskaddr_t endsect; 707 diskaddr_t istart; 708 diskaddr_t jstart; 709 uint64_t isize; 710 uint64_t jsize; 711 uint64_t nblks; 712 713 nblks = geom->dkg_nsect * geom->dkg_nhead; 714 715 fullsz = (uint64_t)geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 716 717 #if defined(_SUNOS_VTOC_16) 718 /* make the vtoc look sane - ha ha */ 719 vtoc->v_version = V_VERSION; 720 vtoc->v_sanity = VTOC_SANE; 721 vtoc->v_nparts = V_NUMPAR; 722 if (vtoc->v_sectorsz == 0) 723 vtoc->v_sectorsz = sectsiz; 724 #endif /* defined(_SUNOS_VTOC_16) */ 725 726 for (i = 0; i < V_NUMPAR; i++) { 727 if (vtoc->v_part[i].p_tag == V_BACKUP) { 728 if (vtoc->v_part[i].p_size != fullsz) { 729 (void) fprintf(stderr, "\ 730 fmthard: Partition %d specifies the full disk and is not equal\n\ 731 full size of disk. The full disk capacity is %llu sectors.\n", i, fullsz); 732 #if defined(sparc) 733 exit(1); 734 #endif 735 } 736 } 737 if (vtoc->v_part[i].p_size == 0) 738 continue; /* Undefined partition */ 739 if ((vtoc->v_part[i].p_start % nblks) || 740 (vtoc->v_part[i].p_size % nblks)) { 741 (void) fprintf(stderr, "\ 742 fmthard: Partition %d not aligned on cylinder boundary \n", i); 743 exit(1); 744 } 745 if (vtoc->v_part[i].p_start > fullsz || 746 vtoc->v_part[i].p_start + 747 vtoc->v_part[i].p_size > fullsz) { 748 (void) fprintf(stderr, "\ 749 fmthard: Partition %d specified as %llu sectors starting at %llu\n\ 750 \tdoes not fit. The full disk contains %llu sectors.\n", 751 i, vtoc->v_part[i].p_size, 752 vtoc->v_part[i].p_start, fullsz); 753 #if defined(sparc) 754 exit(1); 755 #endif 756 } 757 758 if (vtoc->v_part[i].p_tag != V_BACKUP && 759 vtoc->v_part[i].p_size != fullsz) { 760 for (j = 0; j < V_NUMPAR; j++) { 761 if (vtoc->v_part[j].p_tag == V_BACKUP) 762 continue; 763 if (vtoc->v_part[j].p_size == fullsz) 764 continue; 765 isize = vtoc->v_part[i].p_size; 766 jsize = vtoc->v_part[j].p_size; 767 istart = vtoc->v_part[i].p_start; 768 jstart = vtoc->v_part[j].p_start; 769 if ((i != j) && 770 (isize != 0) && (jsize != 0)) { 771 endsect = jstart + jsize -1; 772 if ((jstart <= istart) && 773 (istart <= endsect)) { 774 (void) fprintf(stderr, "\ 775 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 776 \tonly on partition on the full disk partition).\n", 777 i, j); 778 #if defined(sparc) 779 exit(1); 780 #endif 781 } 782 } 783 } 784 } 785 } 786 } 787 788 /* 789 * validate64() 790 * 791 * Validate the new VTOC. 792 */ 793 static void 794 validate64(struct dk_gpt *efi) 795 { 796 int i; 797 int j; 798 int resv_part = 0; 799 diskaddr_t endsect; 800 diskaddr_t fullsz; 801 diskaddr_t istart; 802 diskaddr_t jstart; 803 diskaddr_t isize; 804 diskaddr_t jsize; 805 806 fullsz = lastlba + 1; 807 808 for (i = 0; i < efi->efi_nparts; i++) { 809 if (efi->efi_parts[i].p_size == 0) 810 continue; /* Undefined partition */ 811 if (efi->efi_parts[i].p_tag == V_RESERVED) 812 resv_part++; 813 if (efi->efi_parts[i].p_start > fullsz || 814 efi->efi_parts[i].p_start + 815 efi->efi_parts[i].p_size > fullsz) { 816 (void) fprintf(stderr, "\ 817 fmthard: Partition %d specified as %lld sectors starting at %lld\n\ 818 \tdoes not fit. The full disk contains %lld sectors.\n", 819 i, efi->efi_parts[i].p_size, 820 efi->efi_parts[i].p_start, fullsz); 821 exit(1); 822 } 823 824 if (efi->efi_parts[i].p_tag != V_BACKUP && 825 efi->efi_parts[i].p_size != fullsz) { 826 for (j = 0; j < efi->efi_nparts; j++) { 827 if (efi->efi_parts[j].p_size == fullsz) 828 continue; 829 isize = efi->efi_parts[i].p_size; 830 jsize = efi->efi_parts[j].p_size; 831 istart = efi->efi_parts[i].p_start; 832 jstart = efi->efi_parts[j].p_start; 833 if ((i != j) && 834 (isize != 0) && (jsize != 0)) { 835 endsect = jstart + jsize - 1; 836 if ((jstart <= istart) && 837 (istart <= endsect)) { 838 (void) fprintf(stderr, "\ 839 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 840 \tonly on partition on the full disk partition).\n", 841 i, j); 842 #if defined(sparc) 843 exit(1); 844 #endif 845 } 846 } 847 } 848 } 849 } 850 if (resv_part != 1) { 851 (void) fprintf(stderr, 852 "expected one reserved partition, but found %d\n", 853 resv_part); 854 exit(1); 855 } 856 } 857 858 859 /* 860 * Read the VTOC 861 */ 862 int 863 vread(int fd, struct extvtoc *vtoc, char *devname) 864 { 865 int i; 866 867 if ((i = read_extvtoc(fd, vtoc)) < 0) { 868 if (i == VT_ENOTSUP) { 869 return (1); 870 } 871 if (i == VT_EINVAL) { 872 (void) fprintf(stderr, "%s: Invalid VTOC\n", 873 devname); 874 } else { 875 (void) fprintf(stderr, "%s: Cannot read VTOC\n", 876 devname); 877 } 878 exit(1); 879 } 880 return (0); 881 } 882 883 void 884 vread64(int fd, struct dk_gpt **efi_hdr, char *devname) 885 { 886 int i; 887 888 if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { 889 if (i == VT_EINVAL) 890 (void) fprintf(stderr, 891 "%s: this disk must be labeled first\n", 892 devname); 893 else 894 (void) fprintf(stderr, 895 "%s: read_efi failed %d\n", 896 devname, i); 897 exit(1); 898 } 899 lastlba = (*efi_hdr)->efi_last_u_lba; 900 } 901 902 /* 903 * Write the VTOC 904 */ 905 void 906 vwrite(int fd, struct extvtoc *vtoc, char *devname) 907 { 908 int i; 909 910 if ((i = write_extvtoc(fd, vtoc)) != 0) { 911 if (i == VT_EINVAL) { 912 (void) fprintf(stderr, 913 "%s: invalid entry exists in vtoc\n", 914 devname); 915 } else { 916 (void) fprintf(stderr, "%s: Cannot write VTOC\n", 917 devname); 918 } 919 exit(1); 920 } 921 } 922 923 /* 924 * Write the VTOC 925 */ 926 void 927 vwrite64(int fd, struct dk_gpt *efi, char *devname) 928 { 929 int i; 930 931 if ((i = efi_write(fd, efi)) != 0) { 932 if (i == VT_EINVAL) { 933 (void) fprintf(stderr, 934 "%s: invalid entry exists in vtoc\n", 935 devname); 936 } else { 937 (void) fprintf(stderr, "%s: Cannot write EFI\n", 938 devname); 939 } 940 exit(1); 941 } 942 } 943