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 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 35 * Use is subject to license terms. 36 */ 37 38 /* 39 * Sun Microsystems version of fmthard: 40 * 41 * Supports the following arguments: 42 * 43 * -i Writes VTOC to stdout, rather than disk 44 * -q Quick check: exit code 0 if VTOC ok 45 * -d <data> Incremental changes to the VTOC 46 * -n <vname> Change volume name to <vname> 47 * -s <file> Read VTOC information from <file>, or stdin ("-") 48 * -u <state> Reboot after writing VTOC, according to <state>: 49 * boot: AD_BOOT (standard reboot) 50 * firm: AD_IBOOT (interactive reboot) 51 * 52 * Note that fmthard cannot write a VTOC on an unlabeled disk. 53 * You must use format or SunInstall for this purpose. 54 * (NOTE: the above restriction only applies on Sparc systems). 55 * 56 * The primary motivation for fmthard is to duplicate the 57 * partitioning from disk to disk: 58 * 59 * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 60 */ 61 62 #include <stdio.h> 63 #include <fcntl.h> 64 #include <errno.h> 65 #include <string.h> 66 #include <stdlib.h> 67 #include <unistd.h> 68 #include <sys/types.h> 69 #include <sys/param.h> 70 #include <sys/stat.h> 71 #include <sys/uadmin.h> 72 #include <sys/open.h> 73 #include <sys/vtoc.h> 74 #include <sys/dkio.h> 75 #include <sys/isa_defs.h> 76 #include <sys/efi_partition.h> 77 78 #if defined(_SUNOS_VTOC_16) 79 #include <sys/dklabel.h> 80 #endif 81 82 #include <sys/sysmacros.h> 83 84 #ifndef SECSIZE 85 #define SECSIZE DEV_BSIZE 86 #endif /* SECSIZE */ 87 88 89 /* 90 * External functions. 91 */ 92 extern int read_vtoc(int, struct vtoc *); 93 extern int write_vtoc(int, struct vtoc *); 94 95 /* 96 * Internal functions. 97 */ 98 extern int main(int, char **); 99 static void display(struct dk_geom *, struct vtoc *, char *); 100 static void display64(struct dk_gpt *, char *); 101 static void insert(char *, struct vtoc *); 102 static void insert64(char *, struct dk_gpt *); 103 static void load(FILE *, struct dk_geom *, struct vtoc *); 104 static void load64(FILE *, int fd, struct dk_gpt **); 105 static void usage(void); 106 static void validate(struct dk_geom *, struct vtoc *); 107 static void validate64(struct dk_gpt *); 108 static int vread(int, struct vtoc *, char *); 109 static void vread64(int, struct dk_gpt **, char *); 110 static void vwrite(int, struct vtoc *, char *); 111 static void vwrite64(int, struct dk_gpt *, char *); 112 113 /* 114 * Static variables. 115 */ 116 static char *delta; /* Incremental update */ 117 static short eflag; /* force write of an EFI label */ 118 static short iflag; /* Prints VTOC w/o updating */ 119 static short qflag; /* Check for a formatted disk */ 120 static short uflag; /* Exit to firmware after writing */ 121 /* new vtoc and reboot. Used during */ 122 /* installation of core floppies */ 123 static diskaddr_t lastlba = 0; /* last LBA on 64-bit VTOC */ 124 125 #if defined(sparc) 126 static char *uboot = "boot"; 127 128 #elif defined(i386) 129 /* use installgrub(1M) to install boot blocks */ 130 static char *uboot = ""; 131 #else 132 #error No platform defined. 133 #endif /* various platform-specific definitions */ 134 135 static char *ufirm = "firm"; 136 #if defined(_SUNOS_VTOC_16) 137 static int sectsiz; 138 static struct vtoc disk_vtoc; 139 #endif /* defined(_SUNOS_VTOC_16) */ 140 141 int 142 main(int argc, char **argv) 143 { 144 int fd; 145 int c; 146 char *dfile; 147 char *vname; 148 struct stat statbuf; 149 #if defined(_SUNOS_VTOC_8) 150 struct vtoc disk_vtoc; 151 #endif /* defined(_SUNOS_VTOC_8) */ 152 struct dk_gpt *disk_efi; 153 struct dk_geom disk_geom; 154 int n; 155 156 157 disk_efi = NULL; 158 dfile = NULL; 159 vname = NULL; 160 #if defined(sparc) 161 while ((c = getopt(argc, argv, "ed:u:in:qs:")) != EOF) 162 163 #elif defined(i386) 164 while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF) 165 166 #else 167 #error No platform defined. 168 #endif 169 switch (c) { 170 #if defined(i386) 171 case 'p': 172 case 'b': 173 (void) fprintf(stderr, 174 "fmthard: -p and -b no longer supported." 175 " Use installgrub(1M) to install boot blocks\n"); 176 break; 177 #endif /* defined(i386) */ 178 179 case 'd': 180 delta = optarg; 181 break; 182 case 'e': 183 ++eflag; 184 break; 185 case 'i': 186 ++iflag; 187 break; 188 case 'n': 189 vname = optarg; 190 break; 191 case 'q': 192 ++qflag; 193 break; 194 case 's': 195 dfile = optarg; 196 break; 197 case 'u': 198 if (strcmp(uboot, optarg) == 0) 199 ++uflag; 200 else if (strcmp(ufirm, optarg) == 0) 201 uflag = 2; 202 203 break; 204 default: 205 usage(); 206 } 207 208 209 if (argc - optind != 1) 210 usage(); 211 212 if (stat(argv[optind], (struct stat *)&statbuf) == -1) { 213 (void) fprintf(stderr, 214 "fmthard: Cannot stat device %s\n", 215 argv[optind]); 216 exit(1); 217 } 218 219 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { 220 (void) fprintf(stderr, 221 "fmthard: %s must be a raw device.\n", 222 argv[optind]); 223 exit(1); 224 } 225 226 if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) { 227 (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n", 228 argv[optind], strerror(errno)); 229 exit(1); 230 } 231 232 /* 233 * Get the geometry information for this disk from the driver 234 */ 235 if (!eflag && ioctl(fd, DKIOCGGEOM, &disk_geom)) { 236 #ifdef DEBUG 237 perror("DKIOCGGEOM failed"); 238 #endif /* DEBUG */ 239 if (errno == ENOTSUP) { 240 /* disk has EFI labels */ 241 eflag++; 242 } else { 243 (void) fprintf(stderr, 244 "%s: Cannot get disk geometry\n", argv[optind]); 245 (void) close(fd); 246 exit(1); 247 } 248 } 249 250 /* 251 * Read the vtoc on the disk 252 */ 253 if (!eflag) { 254 if (vread(fd, &disk_vtoc, argv[optind]) == 1) 255 eflag++; 256 } 257 if (eflag && ((dfile == NULL) || qflag)) { 258 vread64(fd, &disk_efi, argv[optind]); 259 } 260 261 /* 262 * Quick check for valid disk: 0 if ok, 1 if not 263 */ 264 if (qflag) { 265 (void) close(fd); 266 if (!eflag) { 267 exit(disk_vtoc.v_sanity == VTOC_SANE ? 0 : 1); 268 } else { 269 exit(disk_efi->efi_version <= EFI_VERSION102 ? 0 : 1); 270 } 271 } 272 273 /* 274 * Incremental changes to the VTOC 275 */ 276 if (delta) { 277 if (!eflag) { 278 insert(delta, &disk_vtoc); 279 validate(&disk_geom, &disk_vtoc); 280 vwrite(fd, &disk_vtoc, argv[optind]); 281 } else { 282 insert64(delta, disk_efi); 283 validate64(disk_efi); 284 vwrite64(fd, disk_efi, argv[optind]); 285 } 286 (void) close(fd); 287 exit(0); 288 } 289 290 if (!dfile && !vname) 291 usage(); 292 293 /* 294 * Read new VTOC from stdin or data file 295 */ 296 if (dfile) { 297 if (strcmp(dfile, "-") == 0) { 298 if (!eflag) 299 load(stdin, &disk_geom, &disk_vtoc); 300 else 301 load64(stdin, fd, &disk_efi); 302 } else { 303 FILE *fp; 304 if ((fp = fopen(dfile, "r")) == NULL) { 305 (void) fprintf(stderr, "Cannot open file %s\n", 306 dfile); 307 (void) close(fd); 308 exit(1); 309 } 310 if (!eflag) 311 load(fp, &disk_geom, &disk_vtoc); 312 else 313 load64(fp, fd, &disk_efi); 314 (void) fclose(fp); 315 } 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 vtoc *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", SECSIZE); 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 %ld %ld\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 vtoc *vtoc) 471 { 472 int part; 473 int tag; 474 uint_t flag; 475 daddr_t start; 476 long size; 477 478 if (sscanf(data, "%d:%d:%x:%ld:%ld", 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 vtoc *vtoc) 533 { 534 int part; 535 int tag; 536 uint_t flag; 537 daddr_t start; 538 long size; 539 char line[256]; 540 int i; 541 long nblks; 542 long 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 = 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 %ld %ld", 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 (void) fprintf(stderr, 680 #if defined(sparc) 681 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ 682 raw-device\n"); 683 684 #elif defined(i386) 685 "Usage: fmthard [ -i ] [ -S ] [-I geom_file] \ 686 -n volumename | -s datafile [ -d arguments] raw-device\n"); 687 688 #else 689 #error No platform defined. 690 #endif 691 exit(2); 692 } 693 694 /* 695 * validate() 696 * 697 * Validate the new VTOC. 698 */ 699 static void 700 validate(struct dk_geom *geom, struct vtoc *vtoc) 701 { 702 int i; 703 int j; 704 long fullsz; 705 long endsect; 706 daddr_t istart; 707 daddr_t jstart; 708 long isize; 709 long jsize; 710 long nblks; 711 712 nblks = geom->dkg_nsect * geom->dkg_nhead; 713 714 fullsz = geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 715 716 #if defined(_SUNOS_VTOC_16) 717 /* make the vtoc look sane - ha ha */ 718 vtoc->v_version = V_VERSION; 719 vtoc->v_sanity = VTOC_SANE; 720 vtoc->v_nparts = V_NUMPAR; 721 if (sectsiz == 0) 722 sectsiz = SECSIZE; 723 if (vtoc->v_sectorsz == 0) 724 vtoc->v_sectorsz = sectsiz; 725 #endif /* defined(_SUNOS_VTOC_16) */ 726 727 for (i = 0; i < V_NUMPAR; i++) { 728 if (vtoc->v_part[i].p_tag == V_BACKUP) { 729 if (vtoc->v_part[i].p_size != fullsz) { 730 (void) fprintf(stderr, "\ 731 fmthard: Partition %d specifies the full disk and is not equal\n\ 732 full size of disk. The full disk capacity is %lu sectors.\n", i, fullsz); 733 #if defined(sparc) 734 exit(1); 735 #endif 736 } 737 } 738 if (vtoc->v_part[i].p_size == 0) 739 continue; /* Undefined partition */ 740 if ((vtoc->v_part[i].p_start % nblks) || 741 (vtoc->v_part[i].p_size % nblks)) { 742 (void) fprintf(stderr, "\ 743 fmthard: Partition %d not aligned on cylinder boundary \n", i); 744 exit(1); 745 } 746 if (vtoc->v_part[i].p_start > fullsz || 747 vtoc->v_part[i].p_start + 748 vtoc->v_part[i].p_size > fullsz) { 749 (void) fprintf(stderr, "\ 750 fmthard: Partition %d specified as %lu sectors starting at %lu\n\ 751 \tdoes not fit. The full disk contains %lu sectors.\n", 752 i, vtoc->v_part[i].p_size, 753 vtoc->v_part[i].p_start, fullsz); 754 #if defined(sparc) 755 exit(1); 756 #endif 757 } 758 759 if (vtoc->v_part[i].p_tag != V_BACKUP && 760 vtoc->v_part[i].p_size != fullsz) { 761 for (j = 0; j < V_NUMPAR; j++) { 762 if (vtoc->v_part[j].p_tag == V_BACKUP) 763 continue; 764 if (vtoc->v_part[j].p_size == fullsz) 765 continue; 766 isize = vtoc->v_part[i].p_size; 767 jsize = vtoc->v_part[j].p_size; 768 istart = vtoc->v_part[i].p_start; 769 jstart = vtoc->v_part[j].p_start; 770 if ((i != j) && 771 (isize != 0) && (jsize != 0)) { 772 endsect = jstart + jsize -1; 773 if ((jstart <= istart) && 774 (istart <= endsect)) { 775 (void) fprintf(stderr, "\ 776 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 777 \tonly on partition on the full disk partition).\n", 778 i, j); 779 #if defined(sparc) 780 exit(1); 781 #endif 782 } 783 } 784 } 785 } 786 } 787 } 788 789 /* 790 * validate64() 791 * 792 * Validate the new VTOC. 793 */ 794 static void 795 validate64(struct dk_gpt *efi) 796 { 797 int i; 798 int j; 799 int resv_part = 0; 800 diskaddr_t endsect; 801 diskaddr_t fullsz; 802 diskaddr_t istart; 803 diskaddr_t jstart; 804 diskaddr_t isize; 805 diskaddr_t jsize; 806 807 fullsz = lastlba + 1; 808 809 for (i = 0; i < efi->efi_nparts; i++) { 810 if (efi->efi_parts[i].p_size == 0) 811 continue; /* Undefined partition */ 812 if (efi->efi_parts[i].p_tag == V_RESERVED) 813 resv_part++; 814 if (efi->efi_parts[i].p_start > fullsz || 815 efi->efi_parts[i].p_start + 816 efi->efi_parts[i].p_size > fullsz) { 817 (void) fprintf(stderr, "\ 818 fmthard: Partition %d specified as %lld sectors starting at %lld\n\ 819 \tdoes not fit. The full disk contains %lld sectors.\n", 820 i, efi->efi_parts[i].p_size, 821 efi->efi_parts[i].p_start, fullsz); 822 exit(1); 823 } 824 825 if (efi->efi_parts[i].p_tag != V_BACKUP && 826 efi->efi_parts[i].p_size != fullsz) { 827 for (j = 0; j < V_NUMPAR; j++) { 828 if (efi->efi_parts[j].p_size == fullsz) 829 continue; 830 isize = efi->efi_parts[i].p_size; 831 jsize = efi->efi_parts[j].p_size; 832 istart = efi->efi_parts[i].p_start; 833 jstart = efi->efi_parts[j].p_start; 834 if ((i != j) && 835 (isize != 0) && (jsize != 0)) { 836 endsect = jstart + jsize - 1; 837 if ((jstart <= istart) && 838 (istart <= endsect)) { 839 (void) fprintf(stderr, "\ 840 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 841 \tonly on partition on the full disk partition).\n", 842 i, j); 843 #if defined(sparc) 844 exit(1); 845 #endif 846 } 847 } 848 } 849 } 850 } 851 if (resv_part != 1) { 852 (void) fprintf(stderr, 853 "expected one reserved partition, but found %d\n", 854 resv_part); 855 exit(1); 856 } 857 } 858 859 860 /* 861 * Read the VTOC 862 */ 863 int 864 vread(int fd, struct vtoc *vtoc, char *devname) 865 { 866 int i; 867 868 if ((i = read_vtoc(fd, vtoc)) < 0) { 869 if (i == VT_ENOTSUP) { 870 return (1); 871 } 872 if (i == VT_EINVAL) { 873 (void) fprintf(stderr, "%s: Invalid VTOC\n", 874 devname); 875 } else { 876 (void) fprintf(stderr, "%s: Cannot read VTOC\n", 877 devname); 878 } 879 exit(1); 880 } 881 return (0); 882 } 883 884 void 885 vread64(int fd, struct dk_gpt **efi_hdr, char *devname) 886 { 887 int i; 888 889 if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { 890 if (i == VT_EINVAL) 891 (void) fprintf(stderr, 892 "%s: this disk must be labeled first\n", 893 devname); 894 else 895 (void) fprintf(stderr, 896 "%s: read_efi failed %d\n", 897 devname, i); 898 exit(1); 899 } 900 lastlba = (*efi_hdr)->efi_last_u_lba; 901 } 902 903 /* 904 * Write the VTOC 905 */ 906 void 907 vwrite(int fd, struct vtoc *vtoc, char *devname) 908 { 909 int i; 910 911 if ((i = write_vtoc(fd, vtoc)) != 0) { 912 if (i == VT_EINVAL) { 913 (void) fprintf(stderr, 914 "%s: invalid entry exists in vtoc\n", 915 devname); 916 } else { 917 (void) fprintf(stderr, "%s: Cannot write VTOC\n", 918 devname); 919 } 920 exit(1); 921 } 922 } 923 924 /* 925 * Write the VTOC 926 */ 927 void 928 vwrite64(int fd, struct dk_gpt *efi, char *devname) 929 { 930 int i; 931 932 if ((i = efi_write(fd, efi)) != 0) { 933 if (i == VT_EINVAL) { 934 (void) fprintf(stderr, 935 "%s: invalid entry exists in vtoc\n", 936 devname); 937 } else { 938 (void) fprintf(stderr, "%s: Cannot write EFI\n", 939 devname); 940 } 941 exit(1); 942 } 943 } 944