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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * 28 * Portions of this source code were provided by International 29 * Computers Limited (ICL) under a development agreement with AT&T. 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 /* 35 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 36 * Use is subject to license terms. 37 */ 38 39 /* 40 * Sun Microsystems version of fmthard: 41 * 42 * Supports the following arguments: 43 * 44 * -i Writes VTOC to stdout, rather than disk 45 * -q Quick check: exit code 0 if VTOC ok 46 * -d <data> Incremental changes to the VTOC 47 * -n <vname> Change volume name to <vname> 48 * -s <file> Read VTOC information from <file>, or stdin ("-") 49 * -u <state> Reboot after writing VTOC, according to <state>: 50 * boot: AD_BOOT (standard reboot) 51 * firm: AD_IBOOT (interactive reboot) 52 * 53 * Note that fmthard cannot write a VTOC on an unlabeled disk. 54 * You must use format or SunInstall for this purpose. 55 * (NOTE: the above restriction only applies on Sparc systems). 56 * 57 * The primary motivation for fmthard is to duplicate the 58 * partitioning from disk to disk: 59 * 60 * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 61 */ 62 63 #include <stdio.h> 64 #include <fcntl.h> 65 #include <errno.h> 66 #include <string.h> 67 #include <stdlib.h> 68 #include <unistd.h> 69 #include <sys/types.h> 70 #include <sys/param.h> 71 #include <sys/stat.h> 72 #include <sys/uadmin.h> 73 #include <sys/open.h> 74 #include <sys/vtoc.h> 75 #include <sys/dkio.h> 76 #include <sys/isa_defs.h> 77 #include <sys/efi_partition.h> 78 79 #if defined(_SUNOS_VTOC_16) 80 #include <sys/dklabel.h> 81 #endif 82 83 #include <sys/sysmacros.h> 84 85 #ifndef SECSIZE 86 #define SECSIZE DEV_BSIZE 87 #endif /* SECSIZE */ 88 89 90 /* 91 * External functions. 92 */ 93 extern int read_vtoc(int, struct vtoc *); 94 extern int write_vtoc(int, struct vtoc *); 95 96 /* 97 * Internal functions. 98 */ 99 extern int main(int, char **); 100 static void display(struct dk_geom *, struct vtoc *, char *); 101 static void display64(struct dk_gpt *, char *); 102 static void insert(char *, struct vtoc *); 103 static void insert64(char *, struct dk_gpt *); 104 static void load(FILE *, struct dk_geom *, struct vtoc *); 105 static void load64(FILE *, int fd, struct dk_gpt **); 106 static void usage(void); 107 static void validate(struct dk_geom *, struct vtoc *); 108 static void validate64(struct dk_gpt *); 109 static int vread(int, struct vtoc *, char *); 110 static void vread64(int, struct dk_gpt **, char *); 111 static void vwrite(int, struct vtoc *, char *); 112 static void vwrite64(int, struct dk_gpt *, char *); 113 114 /* 115 * Static variables. 116 */ 117 static char *delta; /* Incremental update */ 118 static short eflag; /* force write of an EFI label */ 119 static short iflag; /* Prints VTOC w/o updating */ 120 static short qflag; /* Check for a formatted disk */ 121 static short uflag; /* Exit to firmware after writing */ 122 /* new vtoc and reboot. Used during */ 123 /* installation of core floppies */ 124 static diskaddr_t lastlba = 0; /* last LBA on 64-bit VTOC */ 125 126 #if defined(sparc) 127 static char *uboot = "boot"; 128 129 #elif defined(i386) 130 /* use installgrub(1M) to install boot blocks */ 131 static char *uboot = ""; 132 #else 133 #error No platform defined. 134 #endif /* various platform-specific definitions */ 135 136 static char *ufirm = "firm"; 137 #if defined(_SUNOS_VTOC_16) 138 static int sectsiz; 139 static struct vtoc disk_vtoc; 140 #endif /* defined(_SUNOS_VTOC_16) */ 141 142 int 143 main(int argc, char **argv) 144 { 145 int fd; 146 int c; 147 char *dfile; 148 char *vname; 149 struct stat statbuf; 150 #if defined(_SUNOS_VTOC_8) 151 struct vtoc disk_vtoc; 152 #endif /* defined(_SUNOS_VTOC_8) */ 153 struct dk_gpt *disk_efi; 154 struct dk_geom disk_geom; 155 int n; 156 157 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)) { 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 uadmin(A_REBOOT, AD_BOOT, 0); 363 else if (uflag == 2) 364 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 /*NOTREACHED*/ 370 } 371 372 373 374 /* 375 * display () 376 * 377 * display contents of VTOC without writing it to disk 378 */ 379 static void 380 display(struct dk_geom *geom, struct vtoc *vtoc, char *device) 381 { 382 int i; 383 int c; 384 385 /* 386 * Print out the VTOC 387 */ 388 (void) printf("* %s default partition map\n", device); 389 if (*vtoc->v_volume) { 390 (void) printf("* Volume Name: "); 391 for (i = 0; i < LEN_DKL_VVOL; i++) { 392 if ((c = vtoc->v_volume[i]) == 0) 393 break; 394 (void) printf("%c", c); 395 } 396 (void) printf("\n"); 397 } 398 (void) printf("*\n"); 399 (void) printf("* Dimensions:\n"); 400 (void) printf("* %d bytes/sector\n", SECSIZE); 401 (void) printf("* %d sectors/track\n", geom->dkg_nsect); 402 (void) printf("* %d tracks/cylinder\n", geom->dkg_nhead); 403 (void) printf("* %d cylinders\n", geom->dkg_pcyl); 404 (void) printf("* %d accessible cylinders\n", geom->dkg_ncyl); 405 (void) printf("*\n"); 406 (void) printf("* Flags:\n"); 407 (void) printf("* 1: unmountable\n"); 408 (void) printf("* 10: read-only\n"); 409 (void) printf("*\n"); 410 (void) printf( 411 "\n* Partition Tag Flag First Sector Sector Count\n"); 412 for (i = 0; i < V_NUMPAR; i++) { 413 if (vtoc->v_part[i].p_size > 0) 414 (void) printf( 415 " %d %d 0%x %ld %ld\n", 416 i, vtoc->v_part[i].p_tag, 417 vtoc->v_part[i].p_flag, 418 vtoc->v_part[i].p_start, 419 vtoc->v_part[i].p_size); 420 } 421 exit(0); 422 } 423 424 /* 425 * display64 () 426 * 427 * display64 contents of EFI partition without writing it to disk 428 */ 429 static void 430 display64(struct dk_gpt *efi, char *device) 431 { 432 int i; 433 434 /* 435 * Print out the VTOC 436 */ 437 (void) printf("* %s default partition map\n", device); 438 (void) printf("*\n"); 439 (void) printf("* Dimensions:\n"); 440 (void) printf("* %d bytes/sector\n", efi->efi_lbasize); 441 (void) printf("* N/A sectors/track\n"); 442 (void) printf("* N/A tracks/cylinder\n"); 443 (void) printf("* N/A cylinders\n"); 444 (void) printf("* N/A accessible cylinders\n"); 445 (void) printf("*\n"); 446 (void) printf("* Flags:\n"); 447 (void) printf("* 1: unmountable\n"); 448 (void) printf("* 10: read-only\n"); 449 (void) printf("*\n"); 450 (void) printf( 451 "\n* Partition Tag Flag First Sector Sector Count\n"); 452 for (i = 0; i < efi->efi_nparts; i++) { 453 if (efi->efi_parts[i].p_size > 0) 454 (void) printf( 455 " %d %d 0%x %8lld %8lld\n", 456 i, efi->efi_parts[i].p_tag, 457 efi->efi_parts[i].p_flag, 458 efi->efi_parts[i].p_start, 459 efi->efi_parts[i].p_size); 460 } 461 exit(0); 462 } 463 464 465 /* 466 * insert() 467 * 468 * Insert a change into the VTOC. 469 */ 470 static void 471 insert(char *data, struct vtoc *vtoc) 472 { 473 int part; 474 int tag; 475 uint_t flag; 476 daddr_t start; 477 long size; 478 479 if (sscanf(data, "%d:%d:%x:%ld:%ld", 480 &part, &tag, &flag, &start, &size) != 5) { 481 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 482 exit(1); 483 } 484 if (part >= V_NUMPAR) { 485 (void) fprintf(stderr, 486 "Error in data \"%s\": No such partition %x\n", 487 data, part); 488 exit(1); 489 } 490 vtoc->v_part[part].p_tag = (ushort_t)tag; 491 vtoc->v_part[part].p_flag = (ushort_t)flag; 492 vtoc->v_part[part].p_start = start; 493 vtoc->v_part[part].p_size = size; 494 } 495 496 /* 497 * insert64() 498 * 499 * Insert a change into the VTOC. 500 */ 501 static void 502 insert64(char *data, struct dk_gpt *efi) 503 { 504 int part; 505 int tag; 506 uint_t flag; 507 diskaddr_t start; 508 diskaddr_t size; 509 510 if (sscanf(data, "%d:%d:%x:%lld:%lld", 511 &part, &tag, &flag, &start, &size) != 5) { 512 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); 513 exit(1); 514 } 515 if (part >= efi->efi_nparts) { 516 (void) fprintf(stderr, 517 "Error in data \"%s\": No such partition %x\n", 518 data, part); 519 exit(1); 520 } 521 efi->efi_parts[part].p_tag = (ushort_t)tag; 522 efi->efi_parts[part].p_flag = (ushort_t)flag; 523 efi->efi_parts[part].p_start = start; 524 efi->efi_parts[part].p_size = size; 525 } 526 527 /* 528 * load() 529 * 530 * Load VTOC information from a datafile. 531 */ 532 static void 533 load(FILE *fp, struct dk_geom *geom, struct vtoc *vtoc) 534 { 535 int part; 536 int tag; 537 uint_t flag; 538 daddr_t start; 539 long size; 540 char line[256]; 541 int i; 542 long nblks; 543 long fullsz; 544 545 for (i = 0; i < V_NUMPAR; ++i) { 546 vtoc->v_part[i].p_tag = 0; 547 vtoc->v_part[i].p_flag = V_UNMNT; 548 vtoc->v_part[i].p_start = 0; 549 vtoc->v_part[i].p_size = 0; 550 } 551 /* 552 * initialize partition 2, by convention it corresponds to whole 553 * disk. It will be overwritten, if specified in the input datafile 554 */ 555 fullsz = geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; 556 vtoc->v_part[2].p_tag = V_BACKUP; 557 vtoc->v_part[2].p_flag = V_UNMNT; 558 vtoc->v_part[2].p_start = 0; 559 vtoc->v_part[2].p_size = fullsz; 560 561 nblks = geom->dkg_nsect * geom->dkg_nhead; 562 563 while (fgets(line, sizeof (line) - 1, fp)) { 564 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 565 continue; 566 line[strlen(line) - 1] = '\0'; 567 if (sscanf(line, "%d %d %x %ld %ld", 568 &part, &tag, &flag, &start, &size) != 5) { 569 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 570 line); 571 exit(1); 572 } 573 if (part >= V_NUMPAR) { 574 (void) fprintf(stderr, 575 "No such partition %x: \"%s\"\n", 576 part, line); 577 exit(1); 578 } 579 if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) { 580 (void) fprintf(stderr, 581 "Partition %d not aligned on cylinder boundary: \"%s\"\n", 582 part, line); 583 exit(1); 584 } 585 vtoc->v_part[part].p_tag = (ushort_t)tag; 586 vtoc->v_part[part].p_flag = (ushort_t)flag; 587 vtoc->v_part[part].p_start = start; 588 vtoc->v_part[part].p_size = size; 589 } 590 for (part = 0; part < V_NUMPAR; part++) { 591 vtoc->timestamp[part] = (time_t)0; 592 } 593 } 594 595 /* 596 * load64() 597 * 598 * Load VTOC information from a datafile. 599 */ 600 static void 601 load64(FILE *fp, int fd, struct dk_gpt **efi) 602 { 603 int part; 604 int tag; 605 uint_t flag; 606 diskaddr_t start; 607 diskaddr_t size; 608 int nlines = 0; 609 char line[256]; 610 int i; 611 uint_t max_part = 0; 612 char **mem = NULL; 613 614 while (fgets(line, sizeof (line) - 1, fp)) { 615 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') 616 continue; 617 line[strlen(line) - 1] = '\0'; 618 if (sscanf(line, "%d %d %x %lld %lld", 619 &part, &tag, &flag, &start, &size) != 5) { 620 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 621 line); 622 exit(1); 623 } 624 mem = realloc(mem, sizeof (*mem) * (nlines + 1)); 625 if (mem == NULL) { 626 (void) fprintf(stderr, "realloc failed\n"); 627 exit(1); 628 } 629 mem[nlines] = strdup(line); 630 if (mem[nlines] == NULL) { 631 (void) fprintf(stderr, "strdup failed\n"); 632 exit(1); 633 } 634 nlines++; 635 if (part > max_part) 636 max_part = part; 637 } 638 max_part++; 639 640 if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) { 641 (void) fprintf(stderr, 642 "efi_alloc_and_init failed: %d\n", i); 643 exit(1); 644 } 645 for (i = 0; i < (*efi)->efi_nparts; ++i) { 646 (*efi)->efi_parts[i].p_tag = V_UNASSIGNED; 647 (*efi)->efi_parts[i].p_flag = V_UNMNT; 648 (*efi)->efi_parts[i].p_start = 0; 649 (*efi)->efi_parts[i].p_size = 0; 650 } 651 lastlba = (*efi)->efi_last_u_lba; 652 653 for (i = 0; i < nlines; i++) { 654 if (sscanf(mem[i], "%d %d %x %lld %lld", 655 &part, &tag, &flag, &start, &size) != 5) { 656 (void) fprintf(stderr, "Syntax error: \"%s\"\n", 657 line); 658 exit(1); 659 } 660 free(mem[i]); 661 if (part >= (*efi)->efi_nparts) { 662 (void) fprintf(stderr, 663 "No such partition %x: \"%s\"\n", 664 part, line); 665 exit(1); 666 } 667 (*efi)->efi_parts[part].p_tag = (ushort_t)tag; 668 (*efi)->efi_parts[part].p_flag = (ushort_t)flag; 669 (*efi)->efi_parts[part].p_start = start; 670 (*efi)->efi_parts[part].p_size = size; 671 } 672 (*efi)->efi_nparts = max_part; 673 free(mem); 674 } 675 676 677 static void 678 usage() 679 { 680 (void) fprintf(stderr, 681 #if defined(sparc) 682 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ 683 raw-device\n"); 684 685 #elif defined(i386) 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 vtoc *vtoc) 702 { 703 int i; 704 int j; 705 long fullsz; 706 long endsect; 707 daddr_t istart; 708 daddr_t jstart; 709 long isize; 710 long jsize; 711 long nblks; 712 713 nblks = geom->dkg_nsect * geom->dkg_nhead; 714 715 fullsz = 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 (sectsiz == 0) 723 sectsiz = SECSIZE; 724 if (vtoc->v_sectorsz == 0) 725 vtoc->v_sectorsz = sectsiz; 726 #endif /* defined(_SUNOS_VTOC_16) */ 727 728 for (i = 0; i < V_NUMPAR; i++) { 729 if (vtoc->v_part[i].p_tag == V_BACKUP) { 730 if (vtoc->v_part[i].p_size != fullsz) { 731 (void) fprintf(stderr, "\ 732 fmthard: Partition %d specifies the full disk and is not equal\n\ 733 full size of disk. The full disk capacity is %lu sectors.\n", i, fullsz); 734 #if defined(sparc) 735 exit(1); 736 #endif 737 } 738 } 739 if (vtoc->v_part[i].p_size == 0) 740 continue; /* Undefined partition */ 741 if ((vtoc->v_part[i].p_start % nblks) || 742 (vtoc->v_part[i].p_size % nblks)) { 743 (void) fprintf(stderr, "\ 744 fmthard: Partition %d not aligned on cylinder boundary \n", i); 745 exit(1); 746 } 747 if (vtoc->v_part[i].p_start > fullsz || 748 vtoc->v_part[i].p_start + 749 vtoc->v_part[i].p_size > fullsz) { 750 (void) fprintf(stderr, "\ 751 fmthard: Partition %d specified as %lu sectors starting at %lu\n\ 752 \tdoes not fit. The full disk contains %lu sectors.\n", 753 i, vtoc->v_part[i].p_size, 754 vtoc->v_part[i].p_start, fullsz); 755 #if defined(sparc) 756 exit(1); 757 #endif 758 } 759 760 if (vtoc->v_part[i].p_tag != V_BACKUP && 761 vtoc->v_part[i].p_size != fullsz) { 762 for (j = 0; j < V_NUMPAR; j++) { 763 if (vtoc->v_part[j].p_tag == V_BACKUP) 764 continue; 765 if (vtoc->v_part[j].p_size == fullsz) 766 continue; 767 isize = vtoc->v_part[i].p_size; 768 jsize = vtoc->v_part[j].p_size; 769 istart = vtoc->v_part[i].p_start; 770 jstart = vtoc->v_part[j].p_start; 771 if ((i != j) && 772 (isize != 0) && (jsize != 0)) { 773 endsect = jstart + jsize -1; 774 if ((jstart <= istart) && 775 (istart <= endsect)) { 776 (void) fprintf(stderr, "\ 777 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 778 \tonly on partition on the full disk partition).\n", 779 i, j); 780 #if defined(sparc) 781 exit(1); 782 #endif 783 } 784 } 785 } 786 } 787 } 788 } 789 790 /* 791 * validate64() 792 * 793 * Validate the new VTOC. 794 */ 795 static void 796 validate64(struct dk_gpt *efi) 797 { 798 int i; 799 int j; 800 int resv_part = 0; 801 diskaddr_t endsect; 802 diskaddr_t fullsz; 803 diskaddr_t istart; 804 diskaddr_t jstart; 805 diskaddr_t isize; 806 diskaddr_t jsize; 807 808 fullsz = lastlba + 1; 809 810 for (i = 0; i < efi->efi_nparts; i++) { 811 if (efi->efi_parts[i].p_size == 0) 812 continue; /* Undefined partition */ 813 if (efi->efi_parts[i].p_tag == V_RESERVED) 814 resv_part++; 815 if (efi->efi_parts[i].p_start > fullsz || 816 efi->efi_parts[i].p_start + 817 efi->efi_parts[i].p_size > fullsz) { 818 (void) fprintf(stderr, "\ 819 fmthard: Partition %d specified as %lld sectors starting at %lld\n\ 820 \tdoes not fit. The full disk contains %lld sectors.\n", 821 i, efi->efi_parts[i].p_size, 822 efi->efi_parts[i].p_start, fullsz); 823 exit(1); 824 } 825 826 if (efi->efi_parts[i].p_tag != V_BACKUP && 827 efi->efi_parts[i].p_size != fullsz) { 828 for (j = 0; j < V_NUMPAR; j++) { 829 if (efi->efi_parts[j].p_size == fullsz) 830 continue; 831 isize = efi->efi_parts[i].p_size; 832 jsize = efi->efi_parts[j].p_size; 833 istart = efi->efi_parts[i].p_start; 834 jstart = efi->efi_parts[j].p_start; 835 if ((i != j) && 836 (isize != 0) && (jsize != 0)) { 837 endsect = jstart + jsize - 1; 838 if ((jstart <= istart) && 839 (istart <= endsect)) { 840 (void) fprintf(stderr, "\ 841 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ 842 \tonly on partition on the full disk partition).\n", 843 i, j); 844 #if defined(sparc) 845 exit(1); 846 #endif 847 } 848 } 849 } 850 } 851 } 852 if (resv_part != 1) { 853 (void) fprintf(stderr, 854 "expected one reserved partition, but found %d\n", 855 resv_part); 856 exit(1); 857 } 858 } 859 860 861 /* 862 * Read the VTOC 863 */ 864 int 865 vread(int fd, struct vtoc *vtoc, char *devname) 866 { 867 int i; 868 869 if ((i = read_vtoc(fd, vtoc)) < 0) { 870 if (i == VT_ENOTSUP) { 871 return (1); 872 } 873 if (i == VT_EINVAL) { 874 (void) fprintf(stderr, "%s: Invalid VTOC\n", 875 devname); 876 } else { 877 (void) fprintf(stderr, "%s: Cannot read VTOC\n", 878 devname); 879 } 880 exit(1); 881 } 882 return (0); 883 } 884 885 void 886 vread64(int fd, struct dk_gpt **efi_hdr, char *devname) 887 { 888 int i; 889 890 if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { 891 if (i == VT_EINVAL) 892 (void) fprintf(stderr, 893 "%s: this disk must be labeled first\n", 894 devname); 895 else 896 (void) fprintf(stderr, 897 "%s: read_efi failed %d\n", 898 devname, i); 899 exit(1); 900 } 901 lastlba = (*efi_hdr)->efi_last_u_lba; 902 } 903 904 /* 905 * Write the VTOC 906 */ 907 void 908 vwrite(int fd, struct vtoc *vtoc, char *devname) 909 { 910 int i; 911 912 if ((i = write_vtoc(fd, vtoc)) != 0) { 913 if (i == VT_EINVAL) { 914 (void) fprintf(stderr, 915 "%s: invalid entry exists in vtoc\n", 916 devname); 917 } else { 918 (void) fprintf(stderr, "%s: Cannot write VTOC\n", 919 devname); 920 } 921 exit(1); 922 } 923 } 924 925 /* 926 * Write the VTOC 927 */ 928 void 929 vwrite64(int fd, struct dk_gpt *efi, char *devname) 930 { 931 int i; 932 933 if ((i = efi_write(fd, efi)) != 0) { 934 if (i == VT_EINVAL) { 935 (void) fprintf(stderr, 936 "%s: invalid entry exists in vtoc\n", 937 devname); 938 } else { 939 (void) fprintf(stderr, "%s: Cannot write EFI\n", 940 devname); 941 } 942 exit(1); 943 } 944 } 945