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