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