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 2008 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 #if defined(_SUNOS_VTOC_16) 129 static int sectsiz; 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 int n; 147 148 149 disk_efi = NULL; 150 dfile = NULL; 151 vname = NULL; 152 #if defined(sparc) 153 while ((c = getopt(argc, argv, "ed:u:in:qs:")) != EOF) 154 155 #elif defined(i386) 156 while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF) 157 158 #else 159 #error No platform defined. 160 #endif 161 switch (c) { 162 #if defined(i386) 163 case 'p': 164 case 'b': 165 (void) fprintf(stderr, 166 "fmthard: -p and -b no longer supported." 167 " Use installgrub(1M) to install boot blocks\n"); 168 break; 169 #endif /* defined(i386) */ 170 171 case 'd': 172 delta = optarg; 173 break; 174 case 'e': 175 ++eflag; 176 break; 177 case 'i': 178 ++iflag; 179 break; 180 case 'n': 181 vname = optarg; 182 break; 183 case 'q': 184 ++qflag; 185 break; 186 case 's': 187 dfile = optarg; 188 break; 189 case 'u': 190 if (strcmp(uboot, optarg) == 0) 191 ++uflag; 192 else if (strcmp(ufirm, optarg) == 0) 193 uflag = 2; 194 195 break; 196 default: 197 usage(); 198 } 199 200 201 if (argc - optind != 1) 202 usage(); 203 204 if (stat(argv[optind], (struct stat *)&statbuf) == -1) { 205 (void) fprintf(stderr, 206 "fmthard: Cannot stat device %s\n", 207 argv[optind]); 208 exit(1); 209 } 210 211 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { 212 (void) fprintf(stderr, 213 "fmthard: %s must be a raw device.\n", 214 argv[optind]); 215 exit(1); 216 } 217 218 if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) { 219 (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n", 220 argv[optind], strerror(errno)); 221 exit(1); 222 } 223 224 /* 225 * Get the geometry information for this disk from the driver 226 */ 227 if (!eflag && ioctl(fd, DKIOCGGEOM, &disk_geom)) { 228 #ifdef DEBUG 229 perror("DKIOCGGEOM failed"); 230 #endif /* DEBUG */ 231 if (errno == ENOTSUP) { 232 /* disk has EFI labels */ 233 eflag++; 234 } else { 235 (void) fprintf(stderr, 236 "%s: Cannot get disk geometry\n", argv[optind]); 237 (void) close(fd); 238 exit(1); 239 } 240 } 241 242 /* 243 * Read the vtoc on the disk 244 */ 245 if (!eflag) { 246 if (vread(fd, &disk_vtoc, argv[optind]) == 1) 247 eflag++; 248 } 249 if (eflag && ((dfile == NULL) || qflag)) { 250 vread64(fd, &disk_efi, argv[optind]); 251 } 252 253 /* 254 * Quick check for valid disk: 0 if ok, 1 if not 255 */ 256 if (qflag) { 257 (void) close(fd); 258 if (!eflag) { 259 exit(disk_vtoc.v_sanity == VTOC_SANE ? 0 : 1); 260 } else { 261 exit(disk_efi->efi_version <= EFI_VERSION102 ? 0 : 1); 262 } 263 } 264 265 /* 266 * Incremental changes to the VTOC 267 */ 268 if (delta) { 269 if (!eflag) { 270 insert(delta, &disk_vtoc); 271 validate(&disk_geom, &disk_vtoc); 272 vwrite(fd, &disk_vtoc, argv[optind]); 273 } else { 274 insert64(delta, disk_efi); 275 validate64(disk_efi); 276 vwrite64(fd, disk_efi, argv[optind]); 277 } 278 (void) close(fd); 279 exit(0); 280 } 281 282 if (!dfile && !vname) 283 usage(); 284 285 /* 286 * Read new VTOC from stdin or data file 287 */ 288 if (dfile) { 289 if (strcmp(dfile, "-") == 0) { 290 if (!eflag) 291 load(stdin, &disk_geom, &disk_vtoc); 292 else 293 load64(stdin, fd, &disk_efi); 294 } else { 295 FILE *fp; 296 if ((fp = fopen(dfile, "r")) == NULL) { 297 (void) fprintf(stderr, "Cannot open file %s\n", 298 dfile); 299 (void) close(fd); 300 exit(1); 301 } 302 if (!eflag) 303 load(fp, &disk_geom, &disk_vtoc); 304 else 305 load64(fp, fd, &disk_efi); 306 (void) fclose(fp); 307 } 308 } 309 310 311 /* 312 * Print the modified VTOC, rather than updating the disk 313 */ 314 if (iflag) { 315 if (!eflag) 316 display(&disk_geom, &disk_vtoc, argv[optind]); 317 else 318 display64(disk_efi, argv[optind]); 319 (void) close(fd); 320 exit(0); 321 } 322 323 if (vname) { 324 n = MIN(strlen(vname) + 1, LEN_DKL_VVOL); 325 if (!eflag) { 326 (void) memcpy(disk_vtoc.v_volume, vname, n); 327 } else { 328 for (c = 0; c < disk_efi->efi_nparts; c++) { 329 if (disk_efi->efi_parts[c].p_tag == 330 V_RESERVED) { 331 (void) memcpy(&disk_efi->efi_parts[c].p_name, 332 vname, n); 333 } 334 } 335 } 336 337 } 338 /* 339 * Write the new VTOC on the disk 340 */ 341 if (!eflag) { 342 validate(&disk_geom, &disk_vtoc); 343 vwrite(fd, &disk_vtoc, argv[optind]); 344 } else { 345 validate64(disk_efi); 346 vwrite64(fd, disk_efi, argv[optind]); 347 } 348 349 /* 350 * Shut system down after writing a new vtoc to disk 351 * This is used during installation of core floppies. 352 */ 353 if (uflag == 1) 354 (void) uadmin(A_REBOOT, AD_BOOT, 0); 355 else if (uflag == 2) 356 (void) uadmin(A_REBOOT, AD_IBOOT, 0); 357 358 (void) printf("fmthard: New volume table of contents now in place.\n"); 359 360 return (0); 361 } 362 363 364 365 /* 366 * display () 367 * 368 * display contents of VTOC without writing it to disk 369 */ 370 static void 371 display(struct dk_geom *geom, struct extvtoc *vtoc, char *device) 372 { 373 int i; 374 int c; 375 376 /* 377 * Print out the VTOC 378 */ 379 (void) printf("* %s default partition map\n", device); 380 if (*vtoc->v_volume) { 381 (void) printf("* Volume Name: "); 382 for (i = 0; i < LEN_DKL_VVOL; i++) { 383 if ((c = vtoc->v_volume[i]) == 0) 384 break; 385 (void) printf("%c", c); 386 } 387 (void) printf("\n"); 388 } 389 (void) printf("*\n"); 390 (void) printf("* Dimensions:\n"); 391 (void) printf("* %d bytes/sector\n", SECSIZE); 392 (void) printf("* %d sectors/track\n", geom->dkg_nsect); 393 (void) printf("* %d tracks/cylinder\n", geom->dkg_nhead); 394 (void) printf("* %d cylinders\n", geom->dkg_pcyl); 395 (void) printf("* %d accessible cylinders\n", geom->dkg_ncyl); 396 (void) printf("*\n"); 397 (void) printf("* Flags:\n"); 398 (void) printf("* 1: unmountable\n"); 399 (void) printf("* 10: read-only\n"); 400 (void) printf("*\n"); 401 (void) printf( 402 "\n* Partition Tag Flag First Sector Sector Count\n"); 403 for (i = 0; i < V_NUMPAR; i++) { 404 if (vtoc->v_part[i].p_size > 0) 405 (void) printf( 406 " %d %d 0%x %llu %llu\n", 407 i, vtoc->v_part[i].p_tag, 408 vtoc->v_part[i].p_flag, 409 vtoc->v_part[i].p_start, 410 vtoc->v_part[i].p_size); 411 } 412 exit(0); 413 } 414 415 /* 416 * display64 () 417 * 418 * display64 contents of EFI partition without writing it to disk 419 */ 420 static void 421 display64(struct dk_gpt *efi, char *device) 422 { 423 int i; 424 425 /* 426 * Print out the VTOC 427 */ 428 (void) printf("* %s default partition map\n", device); 429 (void) printf("*\n"); 430 (void) printf("* Dimensions:\n"); 431 (void) printf("* %d bytes/sector\n", efi->efi_lbasize); 432 (void) printf("* N/A sectors/track\n"); 433 (void) printf("* N/A tracks/cylinder\n"); 434 (void) printf("* N/A cylinders\n"); 435 (void) printf("* N/A accessible cylinders\n"); 436 (void) printf("*\n"); 437 (void) printf("* Flags:\n"); 438 (void) printf("* 1: unmountable\n"); 439 (void) printf("* 10: read-only\n"); 440 (void) printf("*\n"); 441 (void) printf( 442 "\n* Partition Tag Flag First Sector Sector Count\n"); 443 for (i = 0; i < efi->efi_nparts; i++) { 444 if (efi->efi_parts[i].p_size > 0) 445 (void) printf( 446 " %d %d 0%x %8lld %8lld\n", 447 i, efi->efi_parts[i].p_tag, 448 efi->efi_parts[i].p_flag, 449 efi->efi_parts[i].p_start, 450 efi->efi_parts[i].p_size); 451 } 452 exit(0); 453 } 454 455 456 /* 457 * insert() 458 * 459 * Insert a change into the VTOC. 460 */ 461 static void 462 insert(char *data, struct extvtoc *vtoc) 463 { 464 int part; 465 int tag; 466 uint_t flag; 467 diskaddr_t start; 468 uint64_t size; 469 470 if (sscanf(data, "%d:%d:%x:%llu:%llu", 471 &part, &tag, &flag, &start, &size) != 5) { 472 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 473 exit(1); 474 } 475 if (part >= V_NUMPAR) { 476 (void) fprintf(stderr, 477 "Error in data \"%s\": No such partition %x\n", 478 data, part); 479 exit(1); 480 } 481 vtoc->v_part[part].p_tag = (ushort_t)tag; 482 vtoc->v_part[part].p_flag = (ushort_t)flag; 483 vtoc->v_part[part].p_start = start; 484 vtoc->v_part[part].p_size = size; 485 } 486 487 /* 488 * insert64() 489 * 490 * Insert a change into the VTOC. 491 */ 492 static void 493 insert64(char *data, struct dk_gpt *efi) 494 { 495 int part; 496 int tag; 497 uint_t flag; 498 diskaddr_t start; 499 diskaddr_t size; 500 501 if (sscanf(data, "%d:%d:%x:%lld:%lld", 502 &part, &tag, &flag, &start, &size) != 5) { 503 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 504 exit(1); 505 } 506 if (part >= efi->efi_nparts) { 507 (void) fprintf(stderr, 508 "Error in data \"%s\": No such partition %x\n", 509 data, part); 510 exit(1); 511 } 512 efi->efi_parts[part].p_tag = (ushort_t)tag; 513 efi->efi_parts[part].p_flag = (ushort_t)flag; 514 efi->efi_parts[part].p_start = start; 515 efi->efi_parts[part].p_size = size; 516 } 517 518 /* 519 * load() 520 * 521 * Load VTOC information from a datafile. 522 */ 523 static void 524 load(FILE *fp, struct dk_geom *geom, struct extvtoc *vtoc) 525 { 526 int part; 527 int tag; 528 uint_t flag; 529 diskaddr_t start; 530 uint64_t size; 531 char line[256]; 532 int i; 533 uint64_t nblks; 534 uint64_t fullsz; 535 536 for (i = 0; i < V_NUMPAR; ++i) { 537 vtoc->v_part[i].p_tag = 0; 538 vtoc->v_part[i].p_flag = V_UNMNT; 539 vtoc->v_part[i].p_start = 0; 540 vtoc->v_part[i].p_size = 0; 541 } 542 /* 543 * initialize partition 2, by convention it corresponds to whole 544 * disk. It will be overwritten, if specified in the input datafile 545 */ 546 fullsz = (uint64_t)geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 547 vtoc->v_part[2].p_tag = V_BACKUP; 548 vtoc->v_part[2].p_flag = V_UNMNT; 549 vtoc->v_part[2].p_start = 0; 550 vtoc->v_part[2].p_size = fullsz; 551 552 nblks = geom->dkg_nsect * geom->dkg_nhead; 553 554 while (fgets(line, sizeof (line) - 1, fp)) { 555 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 556 continue; 557 line[strlen(line) - 1] = '\0'; 558 if (sscanf(line, "%d %d %x %llu %llu", 559 &part, &tag, &flag, &start, &size) != 5) { 560 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 561 line); 562 exit(1); 563 } 564 if (part >= V_NUMPAR) { 565 (void) fprintf(stderr, 566 "No such partition %x: \"%s\"\n", 567 part, line); 568 exit(1); 569 } 570 if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) { 571 (void) fprintf(stderr, 572 "Partition %d not aligned on cylinder boundary: \"%s\"\n", 573 part, line); 574 exit(1); 575 } 576 vtoc->v_part[part].p_tag = (ushort_t)tag; 577 vtoc->v_part[part].p_flag = (ushort_t)flag; 578 vtoc->v_part[part].p_start = start; 579 vtoc->v_part[part].p_size = size; 580 } 581 for (part = 0; part < V_NUMPAR; part++) { 582 vtoc->timestamp[part] = (time_t)0; 583 } 584 } 585 586 /* 587 * load64() 588 * 589 * Load VTOC information from a datafile. 590 */ 591 static void 592 load64(FILE *fp, int fd, struct dk_gpt **efi) 593 { 594 int part; 595 int tag; 596 uint_t flag; 597 diskaddr_t start; 598 diskaddr_t size; 599 int nlines = 0; 600 char line[256]; 601 int i; 602 uint_t max_part = 0; 603 char **mem = NULL; 604 605 while (fgets(line, sizeof (line) - 1, fp)) { 606 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 607 continue; 608 line[strlen(line) - 1] = '\0'; 609 if (sscanf(line, "%d %d %x %lld %lld", 610 &part, &tag, &flag, &start, &size) != 5) { 611 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 612 line); 613 exit(1); 614 } 615 mem = realloc(mem, sizeof (*mem) * (nlines + 1)); 616 if (mem == NULL) { 617 (void) fprintf(stderr, "realloc failed\n"); 618 exit(1); 619 } 620 mem[nlines] = strdup(line); 621 if (mem[nlines] == NULL) { 622 (void) fprintf(stderr, "strdup failed\n"); 623 exit(1); 624 } 625 nlines++; 626 if (part > max_part) 627 max_part = part; 628 } 629 max_part++; 630 631 if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) { 632 (void) fprintf(stderr, 633 "efi_alloc_and_init failed: %d\n", i); 634 exit(1); 635 } 636 for (i = 0; i < (*efi)->efi_nparts; ++i) { 637 (*efi)->efi_parts[i].p_tag = V_UNASSIGNED; 638 (*efi)->efi_parts[i].p_flag = V_UNMNT; 639 (*efi)->efi_parts[i].p_start = 0; 640 (*efi)->efi_parts[i].p_size = 0; 641 } 642 lastlba = (*efi)->efi_last_u_lba; 643 644 for (i = 0; i < nlines; i++) { 645 if (sscanf(mem[i], "%d %d %x %lld %lld", 646 &part, &tag, &flag, &start, &size) != 5) { 647 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 648 line); 649 exit(1); 650 } 651 free(mem[i]); 652 if (part >= (*efi)->efi_nparts) { 653 (void) fprintf(stderr, 654 "No such partition %x: \"%s\"\n", 655 part, line); 656 exit(1); 657 } 658 (*efi)->efi_parts[part].p_tag = (ushort_t)tag; 659 (*efi)->efi_parts[part].p_flag = (ushort_t)flag; 660 (*efi)->efi_parts[part].p_start = start; 661 (*efi)->efi_parts[part].p_size = size; 662 } 663 (*efi)->efi_nparts = max_part; 664 free(mem); 665 } 666 667 668 static void 669 usage() 670 { 671 (void) fprintf(stderr, 672 #if defined(sparc) 673 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ 674 raw-device\n"); 675 676 #elif defined(i386) 677 "Usage: fmthard [ -i ] [ -S ] [-I geom_file] \ 678 -n volumename | -s datafile [ -d arguments] raw-device\n"); 679 680 #else 681 #error No platform defined. 682 #endif 683 exit(2); 684 } 685 686 /* 687 * validate() 688 * 689 * Validate the new VTOC. 690 */ 691 static void 692 validate(struct dk_geom *geom, struct extvtoc *vtoc) 693 { 694 int i; 695 int j; 696 uint64_t fullsz; 697 diskaddr_t endsect; 698 diskaddr_t istart; 699 diskaddr_t jstart; 700 uint64_t isize; 701 uint64_t jsize; 702 uint64_t nblks; 703 704 nblks = geom->dkg_nsect * geom->dkg_nhead; 705 706 fullsz = (uint64_t)geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 707 708 #if defined(_SUNOS_VTOC_16) 709 /* make the vtoc look sane - ha ha */ 710 vtoc->v_version = V_VERSION; 711 vtoc->v_sanity = VTOC_SANE; 712 vtoc->v_nparts = V_NUMPAR; 713 if (sectsiz == 0) 714 sectsiz = SECSIZE; 715 if (vtoc->v_sectorsz == 0) 716 vtoc->v_sectorsz = sectsiz; 717 #endif /* defined(_SUNOS_VTOC_16) */ 718 719 for (i = 0; i < V_NUMPAR; i++) { 720 if (vtoc->v_part[i].p_tag == V_BACKUP) { 721 if (vtoc->v_part[i].p_size != fullsz) { 722 (void) fprintf(stderr, "\ 723 fmthard: Partition %d specifies the full disk and is not equal\n\ 724 full size of disk. The full disk capacity is %llu sectors.\n", i, fullsz); 725 #if defined(sparc) 726 exit(1); 727 #endif 728 } 729 } 730 if (vtoc->v_part[i].p_size == 0) 731 continue; /* Undefined partition */ 732 if ((vtoc->v_part[i].p_start % nblks) || 733 (vtoc->v_part[i].p_size % nblks)) { 734 (void) fprintf(stderr, "\ 735 fmthard: Partition %d not aligned on cylinder boundary \n", i); 736 exit(1); 737 } 738 if (vtoc->v_part[i].p_start > fullsz || 739 vtoc->v_part[i].p_start + 740 vtoc->v_part[i].p_size > fullsz) { 741 (void) fprintf(stderr, "\ 742 fmthard: Partition %d specified as %llu sectors starting at %llu\n\ 743 \tdoes not fit. The full disk contains %llu sectors.\n", 744 i, vtoc->v_part[i].p_size, 745 vtoc->v_part[i].p_start, fullsz); 746 #if defined(sparc) 747 exit(1); 748 #endif 749 } 750 751 if (vtoc->v_part[i].p_tag != V_BACKUP && 752 vtoc->v_part[i].p_size != fullsz) { 753 for (j = 0; j < V_NUMPAR; j++) { 754 if (vtoc->v_part[j].p_tag == V_BACKUP) 755 continue; 756 if (vtoc->v_part[j].p_size == fullsz) 757 continue; 758 isize = vtoc->v_part[i].p_size; 759 jsize = vtoc->v_part[j].p_size; 760 istart = vtoc->v_part[i].p_start; 761 jstart = vtoc->v_part[j].p_start; 762 if ((i != j) && 763 (isize != 0) && (jsize != 0)) { 764 endsect = jstart + jsize -1; 765 if ((jstart <= istart) && 766 (istart <= endsect)) { 767 (void) fprintf(stderr, "\ 768 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 769 \tonly on partition on the full disk partition).\n", 770 i, j); 771 #if defined(sparc) 772 exit(1); 773 #endif 774 } 775 } 776 } 777 } 778 } 779 } 780 781 /* 782 * validate64() 783 * 784 * Validate the new VTOC. 785 */ 786 static void 787 validate64(struct dk_gpt *efi) 788 { 789 int i; 790 int j; 791 int resv_part = 0; 792 diskaddr_t endsect; 793 diskaddr_t fullsz; 794 diskaddr_t istart; 795 diskaddr_t jstart; 796 diskaddr_t isize; 797 diskaddr_t jsize; 798 799 fullsz = lastlba + 1; 800 801 for (i = 0; i < efi->efi_nparts; i++) { 802 if (efi->efi_parts[i].p_size == 0) 803 continue; /* Undefined partition */ 804 if (efi->efi_parts[i].p_tag == V_RESERVED) 805 resv_part++; 806 if (efi->efi_parts[i].p_start > fullsz || 807 efi->efi_parts[i].p_start + 808 efi->efi_parts[i].p_size > fullsz) { 809 (void) fprintf(stderr, "\ 810 fmthard: Partition %d specified as %lld sectors starting at %lld\n\ 811 \tdoes not fit. The full disk contains %lld sectors.\n", 812 i, efi->efi_parts[i].p_size, 813 efi->efi_parts[i].p_start, fullsz); 814 exit(1); 815 } 816 817 if (efi->efi_parts[i].p_tag != V_BACKUP && 818 efi->efi_parts[i].p_size != fullsz) { 819 for (j = 0; j < efi->efi_nparts; j++) { 820 if (efi->efi_parts[j].p_size == fullsz) 821 continue; 822 isize = efi->efi_parts[i].p_size; 823 jsize = efi->efi_parts[j].p_size; 824 istart = efi->efi_parts[i].p_start; 825 jstart = efi->efi_parts[j].p_start; 826 if ((i != j) && 827 (isize != 0) && (jsize != 0)) { 828 endsect = jstart + jsize - 1; 829 if ((jstart <= istart) && 830 (istart <= endsect)) { 831 (void) fprintf(stderr, "\ 832 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 833 \tonly on partition on the full disk partition).\n", 834 i, j); 835 #if defined(sparc) 836 exit(1); 837 #endif 838 } 839 } 840 } 841 } 842 } 843 if (resv_part != 1) { 844 (void) fprintf(stderr, 845 "expected one reserved partition, but found %d\n", 846 resv_part); 847 exit(1); 848 } 849 } 850 851 852 /* 853 * Read the VTOC 854 */ 855 int 856 vread(int fd, struct extvtoc *vtoc, char *devname) 857 { 858 int i; 859 860 if ((i = read_extvtoc(fd, vtoc)) < 0) { 861 if (i == VT_ENOTSUP) { 862 return (1); 863 } 864 if (i == VT_EINVAL) { 865 (void) fprintf(stderr, "%s: Invalid VTOC\n", 866 devname); 867 } else { 868 (void) fprintf(stderr, "%s: Cannot read VTOC\n", 869 devname); 870 } 871 exit(1); 872 } 873 return (0); 874 } 875 876 void 877 vread64(int fd, struct dk_gpt **efi_hdr, char *devname) 878 { 879 int i; 880 881 if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { 882 if (i == VT_EINVAL) 883 (void) fprintf(stderr, 884 "%s: this disk must be labeled first\n", 885 devname); 886 else 887 (void) fprintf(stderr, 888 "%s: read_efi failed %d\n", 889 devname, i); 890 exit(1); 891 } 892 lastlba = (*efi_hdr)->efi_last_u_lba; 893 } 894 895 /* 896 * Write the VTOC 897 */ 898 void 899 vwrite(int fd, struct extvtoc *vtoc, char *devname) 900 { 901 int i; 902 903 if ((i = write_extvtoc(fd, vtoc)) != 0) { 904 if (i == VT_EINVAL) { 905 (void) fprintf(stderr, 906 "%s: invalid entry exists in vtoc\n", 907 devname); 908 } else { 909 (void) fprintf(stderr, "%s: Cannot write VTOC\n", 910 devname); 911 } 912 exit(1); 913 } 914 } 915 916 /* 917 * Write the VTOC 918 */ 919 void 920 vwrite64(int fd, struct dk_gpt *efi, char *devname) 921 { 922 int i; 923 924 if ((i = efi_write(fd, efi)) != 0) { 925 if (i == VT_EINVAL) { 926 (void) fprintf(stderr, 927 "%s: invalid entry exists in vtoc\n", 928 devname); 929 } else { 930 (void) fprintf(stderr, "%s: Cannot write EFI\n", 931 devname); 932 } 933 exit(1); 934 } 935 } 936