dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fmthard / fmthard.c
blob588afbca63ee8d097f478085440c31d6b6fbb682
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
27 * Portions of this source code were provided by International
28 * Computers Limited (ICL) under a development agreement with AT&T.
32 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
33 * Use is subject to license terms.
37 * Sun Microsystems version of fmthard:
39 * Supports the following arguments:
41 * -i Writes VTOC to stdout, rather than disk
42 * -q Quick check: exit code 0 if VTOC ok
43 * -d <data> Incremental changes to the VTOC
44 * -n <vname> Change volume name to <vname>
45 * -s <file> Read VTOC information from <file>, or stdin ("-")
46 * -u <state> Reboot after writing VTOC, according to <state>:
47 * boot: AD_BOOT (standard reboot)
48 * firm: AD_IBOOT (interactive reboot)
50 * Note that fmthard cannot write a VTOC on an unlabeled disk.
51 * You must use format or SunInstall for this purpose.
52 * (NOTE: the above restriction only applies on Sparc systems).
54 * The primary motivation for fmthard is to duplicate the
55 * partitioning from disk to disk:
57 * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2
60 #include <stdio.h>
61 #include <fcntl.h>
62 #include <errno.h>
63 #include <string.h>
64 #include <stdlib.h>
65 #include <unistd.h>
66 #include <sys/types.h>
67 #include <sys/param.h>
68 #include <sys/int_limits.h>
69 #include <sys/stat.h>
70 #include <sys/uadmin.h>
71 #include <sys/open.h>
72 #include <sys/vtoc.h>
73 #include <sys/dkio.h>
74 #include <sys/isa_defs.h>
75 #include <sys/efi_partition.h>
77 #if defined(_SUNOS_VTOC_16)
78 #include <sys/dklabel.h>
79 #endif
81 #include <sys/sysmacros.h>
83 #ifndef SECSIZE
84 #define SECSIZE DEV_BSIZE
85 #endif /* SECSIZE */
88 * Internal functions.
90 extern int main(int, char **);
91 static void display(struct dk_geom *, struct extvtoc *, char *);
92 static void display64(struct dk_gpt *, char *);
93 static void insert(char *, struct extvtoc *);
94 static void insert64(char *, struct dk_gpt *);
95 static void load(FILE *, struct dk_geom *, struct extvtoc *);
96 static void load64(FILE *, int fd, struct dk_gpt **);
97 static void usage(void);
98 static void validate(struct dk_geom *, struct extvtoc *);
99 static void validate64(struct dk_gpt *);
100 static int vread(int, struct extvtoc *, char *);
101 static void vread64(int, struct dk_gpt **, char *);
102 static void vwrite(int, struct extvtoc *, char *);
103 static void vwrite64(int, struct dk_gpt *, char *);
106 * Static variables.
108 static char *delta; /* Incremental update */
109 static short eflag; /* force write of an EFI label */
110 static short iflag; /* Prints VTOC w/o updating */
111 static short qflag; /* Check for a formatted disk */
112 static short uflag; /* Exit to firmware after writing */
113 /* new vtoc and reboot. Used during */
114 /* installation of core floppies */
115 static diskaddr_t lastlba = 0; /* last LBA on 64-bit VTOC */
117 #if defined(sparc)
118 static char *uboot = "boot";
120 #elif defined(i386)
121 /* use installboot(1M) to install boot blocks */
122 static char *uboot = "";
123 #else
124 #error No platform defined.
125 #endif /* various platform-specific definitions */
127 static char *ufirm = "firm";
128 static int sectsiz;
129 #if defined(_SUNOS_VTOC_16)
130 static struct extvtoc disk_vtoc;
131 #endif /* defined(_SUNOS_VTOC_16) */
134 main(int argc, char **argv)
136 int fd;
137 int c;
138 char *dfile;
139 char *vname;
140 struct stat statbuf;
141 #if defined(_SUNOS_VTOC_8)
142 struct extvtoc disk_vtoc;
143 #endif /* defined(_SUNOS_VTOC_8) */
144 struct dk_gpt *disk_efi;
145 struct dk_geom disk_geom;
146 struct dk_minfo minfo;
147 int n;
150 disk_efi = NULL;
151 dfile = NULL;
152 vname = NULL;
153 #if defined(sparc)
154 while ((c = getopt(argc, argv, "ed:u:in:qs:")) != EOF)
156 #elif defined(i386)
157 while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF)
159 #else
160 #error No platform defined.
161 #endif
162 switch (c) {
163 #if defined(i386)
164 case 'p':
165 case 'b':
166 (void) fprintf(stderr,
167 "fmthard: -p and -b no longer supported."
168 " Use installboot(1M) to install boot blocks\n");
169 break;
170 #endif /* defined(i386) */
172 case 'd':
173 delta = optarg;
174 break;
175 case 'e':
176 ++eflag;
177 break;
178 case 'i':
179 ++iflag;
180 break;
181 case 'n':
182 vname = optarg;
183 break;
184 case 'q':
185 ++qflag;
186 break;
187 case 's':
188 dfile = optarg;
189 break;
190 case 'u':
191 if (strcmp(uboot, optarg) == 0)
192 ++uflag;
193 else if (strcmp(ufirm, optarg) == 0)
194 uflag = 2;
196 break;
197 default:
198 usage();
202 if (argc - optind != 1)
203 usage();
205 if (stat(argv[optind], (struct stat *)&statbuf) == -1) {
206 (void) fprintf(stderr,
207 "fmthard: Cannot stat device %s\n",
208 argv[optind]);
209 exit(1);
212 if ((statbuf.st_mode & S_IFMT) != S_IFCHR) {
213 (void) fprintf(stderr,
214 "fmthard: %s must be a raw device.\n",
215 argv[optind]);
216 exit(1);
219 if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) {
220 (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n",
221 argv[optind], strerror(errno));
222 exit(1);
225 if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == 0) {
226 sectsiz = minfo.dki_lbsize;
229 if (sectsiz == 0) {
230 sectsiz = SECSIZE;
234 * Get the geometry information for this disk from the driver
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);
252 * Read the vtoc on the disk
254 if (!eflag) {
255 if (vread(fd, &disk_vtoc, argv[optind]) == 1)
256 eflag++;
258 if (eflag && ((dfile == NULL) || qflag)) {
259 vread64(fd, &disk_efi, argv[optind]);
263 * Quick check for valid disk: 0 if ok, 1 if not
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);
275 * Incremental changes to the VTOC
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]);
287 (void) close(fd);
288 exit(0);
291 if (!dfile && !vname)
292 usage();
295 * Read new VTOC from stdin or data file
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);
311 if (!eflag)
312 load(fp, &disk_geom, &disk_vtoc);
313 else
314 load64(fp, fd, &disk_efi);
315 (void) fclose(fp);
320 * Print the modified VTOC, rather than updating the disk
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);
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);
347 * Write the new VTOC on the disk
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]);
358 * Shut system down after writing a new vtoc to disk
359 * This is used during installation of core floppies.
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);
366 (void) printf("fmthard: New volume table of contents now in place.\n");
368 return (0);
374 * display ()
376 * display contents of VTOC without writing it to disk
378 static void
379 display(struct dk_geom *geom, struct extvtoc *vtoc, char *device)
381 int i;
382 int c;
385 * Print out the VTOC
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);
395 (void) printf("\n");
397 (void) printf("*\n");
398 (void) printf("* Dimensions:\n");
399 (void) printf("* %d bytes/sector\n", sectsiz);
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 %llu %llu\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);
420 exit(0);
424 * display64 ()
426 * display64 contents of EFI partition without writing it to disk
428 static void
429 display64(struct dk_gpt *efi, char *device)
431 int i;
434 * Print out the VTOC
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);
460 exit(0);
465 * insert()
467 * Insert a change into the VTOC.
469 static void
470 insert(char *data, struct extvtoc *vtoc)
472 int part;
473 int tag;
474 uint_t flag;
475 diskaddr_t start;
476 uint64_t size;
478 if (sscanf(data, "%d:%d:%x:%llu:%llu",
479 &part, &tag, &flag, &start, &size) != 5) {
480 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data);
481 exit(1);
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);
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;
496 * insert64()
498 * Insert a change into the VTOC.
500 static void
501 insert64(char *data, struct dk_gpt *efi)
503 int part;
504 int tag;
505 uint_t flag;
506 diskaddr_t start;
507 diskaddr_t size;
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);
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);
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;
527 * load()
529 * Load VTOC information from a datafile.
531 static void
532 load(FILE *fp, struct dk_geom *geom, struct extvtoc *vtoc)
534 int part;
535 int tag;
536 uint_t flag;
537 diskaddr_t start;
538 uint64_t size;
539 char line[256];
540 int i;
541 uint64_t nblks;
542 uint64_t fullsz;
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;
551 * initialize partition 2, by convention it corresponds to whole
552 * disk. It will be overwritten, if specified in the input datafile
554 fullsz = (uint64_t)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;
560 nblks = geom->dkg_nsect * geom->dkg_nhead;
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 %llu %llu",
567 &part, &tag, &flag, &start, &size) != 5) {
568 (void) fprintf(stderr, "Syntax error: \"%s\"\n",
569 line);
570 exit(1);
572 if (part >= V_NUMPAR) {
573 (void) fprintf(stderr,
574 "No such partition %x: \"%s\"\n",
575 part, line);
576 exit(1);
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);
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;
589 for (part = 0; part < V_NUMPAR; part++) {
590 vtoc->timestamp[part] = (time_t)0;
595 * load64()
597 * Load VTOC information from a datafile.
599 static void
600 load64(FILE *fp, int fd, struct dk_gpt **efi)
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;
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);
623 mem = reallocarray(mem, nlines + 1, sizeof (*mem));
624 if (mem == NULL) {
625 (void) fprintf(stderr, "realloc failed\n");
626 exit(1);
628 mem[nlines] = strdup(line);
629 if (mem[nlines] == NULL) {
630 (void) fprintf(stderr, "strdup failed\n");
631 exit(1);
633 nlines++;
634 if (part > max_part)
635 max_part = part;
637 max_part++;
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);
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;
650 lastlba = (*efi)->efi_last_u_lba;
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);
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);
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;
671 (*efi)->efi_nparts = max_part;
672 free(mem);
676 static void
677 usage()
679 #if defined(sparc)
680 (void) fprintf(stderr,
681 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \
682 raw-device\n");
684 #elif defined(i386)
685 (void) fprintf(stderr,
686 "Usage: fmthard [ -i ] [ -S ] [-I geom_file] \
687 -n volumename | -s datafile [ -d arguments] raw-device\n");
689 #else
690 #error No platform defined.
691 #endif
692 exit(2);
696 * validate()
698 * Validate the new VTOC.
700 static void
701 validate(struct dk_geom *geom, struct extvtoc *vtoc)
703 int i;
704 int j;
705 uint64_t fullsz;
706 diskaddr_t endsect;
707 diskaddr_t istart;
708 diskaddr_t jstart;
709 uint64_t isize;
710 uint64_t jsize;
711 uint64_t nblks;
713 nblks = geom->dkg_nsect * geom->dkg_nhead;
715 fullsz = (uint64_t)geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead;
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 (vtoc->v_sectorsz == 0)
723 vtoc->v_sectorsz = sectsiz;
724 #endif /* defined(_SUNOS_VTOC_16) */
726 for (i = 0; i < V_NUMPAR; i++) {
727 if (vtoc->v_part[i].p_tag == V_BACKUP) {
728 if (vtoc->v_part[i].p_size != fullsz) {
729 (void) fprintf(stderr, "\
730 fmthard: Partition %d specifies the full disk and is not equal\n\
731 full size of disk. The full disk capacity is %llu sectors.\n", i, fullsz);
732 #if defined(sparc)
733 exit(1);
734 #endif
737 if (vtoc->v_part[i].p_size == 0)
738 continue; /* Undefined partition */
739 if ((vtoc->v_part[i].p_start % nblks) ||
740 (vtoc->v_part[i].p_size % nblks)) {
741 (void) fprintf(stderr, "\
742 fmthard: Partition %d not aligned on cylinder boundary \n", i);
743 exit(1);
745 if (vtoc->v_part[i].p_start > fullsz ||
746 vtoc->v_part[i].p_start +
747 vtoc->v_part[i].p_size > fullsz) {
748 (void) fprintf(stderr, "\
749 fmthard: Partition %d specified as %llu sectors starting at %llu\n\
750 \tdoes not fit. The full disk contains %llu sectors.\n",
751 i, vtoc->v_part[i].p_size,
752 vtoc->v_part[i].p_start, fullsz);
753 #if defined(sparc)
754 exit(1);
755 #endif
758 if (vtoc->v_part[i].p_tag != V_BACKUP &&
759 vtoc->v_part[i].p_size != fullsz) {
760 for (j = 0; j < V_NUMPAR; j++) {
761 if (vtoc->v_part[j].p_tag == V_BACKUP)
762 continue;
763 if (vtoc->v_part[j].p_size == fullsz)
764 continue;
765 isize = vtoc->v_part[i].p_size;
766 jsize = vtoc->v_part[j].p_size;
767 istart = vtoc->v_part[i].p_start;
768 jstart = vtoc->v_part[j].p_start;
769 if ((i != j) &&
770 (isize != 0) && (jsize != 0)) {
771 endsect = jstart + jsize -1;
772 if ((jstart <= istart) &&
773 (istart <= endsect)) {
774 (void) fprintf(stderr, "\
775 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\
776 \tonly on partition on the full disk partition).\n",
777 i, j);
778 #if defined(sparc)
779 exit(1);
780 #endif
789 * validate64()
791 * Validate the new VTOC.
793 static void
794 validate64(struct dk_gpt *efi)
796 int i;
797 int j;
798 int resv_part = 0;
799 diskaddr_t endsect;
800 diskaddr_t fullsz;
801 diskaddr_t istart;
802 diskaddr_t jstart;
803 diskaddr_t isize;
804 diskaddr_t jsize;
806 fullsz = lastlba + 1;
808 for (i = 0; i < efi->efi_nparts; i++) {
809 if (efi->efi_parts[i].p_size == 0)
810 continue; /* Undefined partition */
811 if (efi->efi_parts[i].p_tag == V_RESERVED)
812 resv_part++;
813 if (efi->efi_parts[i].p_start > fullsz ||
814 efi->efi_parts[i].p_start +
815 efi->efi_parts[i].p_size > fullsz) {
816 (void) fprintf(stderr, "\
817 fmthard: Partition %d specified as %lld sectors starting at %lld\n\
818 \tdoes not fit. The full disk contains %lld sectors.\n",
819 i, efi->efi_parts[i].p_size,
820 efi->efi_parts[i].p_start, fullsz);
821 exit(1);
824 if (efi->efi_parts[i].p_tag != V_BACKUP &&
825 efi->efi_parts[i].p_size != fullsz) {
826 for (j = 0; j < efi->efi_nparts; j++) {
827 if (efi->efi_parts[j].p_size == fullsz)
828 continue;
829 isize = efi->efi_parts[i].p_size;
830 jsize = efi->efi_parts[j].p_size;
831 istart = efi->efi_parts[i].p_start;
832 jstart = efi->efi_parts[j].p_start;
833 if ((i != j) &&
834 (isize != 0) && (jsize != 0)) {
835 endsect = jstart + jsize - 1;
836 if ((jstart <= istart) &&
837 (istart <= endsect)) {
838 (void) fprintf(stderr, "\
839 fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\
840 \tonly on partition on the full disk partition).\n",
841 i, j);
842 #if defined(sparc)
843 exit(1);
844 #endif
850 if (resv_part != 1) {
851 (void) fprintf(stderr,
852 "expected one reserved partition, but found %d\n",
853 resv_part);
854 exit(1);
860 * Read the VTOC
863 vread(int fd, struct extvtoc *vtoc, char *devname)
865 int i;
867 if ((i = read_extvtoc(fd, vtoc)) < 0) {
868 if (i == VT_ENOTSUP) {
869 return (1);
871 if (i == VT_EINVAL) {
872 (void) fprintf(stderr, "%s: Invalid VTOC\n",
873 devname);
874 } else {
875 (void) fprintf(stderr, "%s: Cannot read VTOC\n",
876 devname);
878 exit(1);
880 return (0);
883 void
884 vread64(int fd, struct dk_gpt **efi_hdr, char *devname)
886 int i;
888 if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) {
889 if (i == VT_EINVAL)
890 (void) fprintf(stderr,
891 "%s: this disk must be labeled first\n",
892 devname);
893 else
894 (void) fprintf(stderr,
895 "%s: read_efi failed %d\n",
896 devname, i);
897 exit(1);
899 lastlba = (*efi_hdr)->efi_last_u_lba;
903 * Write the VTOC
905 void
906 vwrite(int fd, struct extvtoc *vtoc, char *devname)
908 int i;
910 if ((i = write_extvtoc(fd, vtoc)) != 0) {
911 if (i == VT_EINVAL) {
912 (void) fprintf(stderr,
913 "%s: invalid entry exists in vtoc\n",
914 devname);
915 } else {
916 (void) fprintf(stderr, "%s: Cannot write VTOC\n",
917 devname);
919 exit(1);
924 * Write the VTOC
926 void
927 vwrite64(int fd, struct dk_gpt *efi, char *devname)
929 int i;
931 if ((i = efi_write(fd, efi)) != 0) {
932 if (i == VT_EINVAL) {
933 (void) fprintf(stderr,
934 "%s: invalid entry exists in vtoc\n",
935 devname);
936 } else {
937 (void) fprintf(stderr, "%s: Cannot write EFI\n",
938 devname);
940 exit(1);