1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
23
24
25 /*
26 *
27 * Portions of this source code were provided by International
28 * Computers Limited (ICL) under a development agreement with AT&T.
29 */
30
31 /*
32 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
33 * Use is subject to license terms.
34 */
35
36 /*
37 * Sun Microsystems version of fmthard:
38 *
39 * Supports the following arguments:
40 *
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)
49 *
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).
53 *
54 * The primary motivation for fmthard is to duplicate the
55 * partitioning from disk to disk:
56 *
57 * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2
58 */
59
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>
76
77 #if defined(_SUNOS_VTOC_16)
78 #include <sys/dklabel.h>
79 #endif
80
81 #include <sys/sysmacros.h>
82
83 #ifndef SECSIZE
84 #define SECSIZE DEV_BSIZE
85 #endif /* SECSIZE */
86
87 /*
88 * Internal functions.
89 */
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 *);
104
105 /*
106 * Static variables.
107 */
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 */
116
117 #if defined(sparc)
118 static char *uboot = "boot";
119
120 #elif defined(i386)
121 /* use installgrub(1M) to install boot blocks */
122 static char *uboot = "";
123 #else
124 #error No platform defined.
125 #endif /* various platform-specific definitions */
126
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) */
132
133 int
main(int argc,char ** argv)134 main(int argc, char **argv)
135 {
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;
148
149
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)
155
156 #elif defined(i386)
157 while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF)
158
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 installgrub(1M) to install boot blocks\n");
169 break;
170 #endif /* defined(i386) */
171
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;
195
196 break;
197 default:
198 usage();
199 }
200
201
202 if (argc - optind != 1)
203 usage();
204
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);
210 }
211
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);
217 }
218
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);
223 }
224
225 if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == 0) {
226 sectsiz = minfo.dki_lbsize;
227 }
228
229 if (sectsiz == 0) {
230 sectsiz = SECSIZE;
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 * Print the modified VTOC, rather than updating the disk
321 */
322 if (iflag) {
323 if (!eflag)
324 display(&disk_geom, &disk_vtoc, argv[optind]);
325 else
326 display64(disk_efi, argv[optind]);
327 (void) close(fd);
328 exit(0);
329 }
330
331 if (vname) {
332 n = MIN(strlen(vname) + 1, LEN_DKL_VVOL);
333 if (!eflag) {
334 (void) memcpy(disk_vtoc.v_volume, vname, n);
335 } else {
336 for (c = 0; c < disk_efi->efi_nparts; c++) {
337 if (disk_efi->efi_parts[c].p_tag ==
338 V_RESERVED) {
339 (void) memcpy(&disk_efi->efi_parts[c].p_name,
340 vname, n);
341 }
342 }
343 }
344
345 }
346 /*
347 * Write the new VTOC on the disk
348 */
349 if (!eflag) {
350 validate(&disk_geom, &disk_vtoc);
351 vwrite(fd, &disk_vtoc, argv[optind]);
352 } else {
353 validate64(disk_efi);
354 vwrite64(fd, disk_efi, argv[optind]);
355 }
356
357 /*
358 * Shut system down after writing a new vtoc to disk
359 * This is used during installation of core floppies.
360 */
361 if (uflag == 1)
362 (void) uadmin(A_REBOOT, AD_BOOT, 0);
363 else if (uflag == 2)
364 (void) uadmin(A_REBOOT, AD_IBOOT, 0);
365
366 (void) printf("fmthard: New volume table of contents now in place.\n");
367
368 return (0);
369 }
370
371
372
373 /*
374 * display ()
375 *
376 * display contents of VTOC without writing it to disk
377 */
378 static void
display(struct dk_geom * geom,struct extvtoc * vtoc,char * device)379 display(struct dk_geom *geom, struct extvtoc *vtoc, char *device)
380 {
381 int i;
382 int c;
383
384 /*
385 * Print out the VTOC
386 */
387 (void) printf("* %s default partition map\n", device);
388 if (*vtoc->v_volume) {
389 (void) printf("* Volume Name: ");
390 for (i = 0; i < LEN_DKL_VVOL; i++) {
391 if ((c = vtoc->v_volume[i]) == 0)
392 break;
393 (void) printf("%c", c);
394 }
395 (void) printf("\n");
396 }
397 (void) printf("*\n");
398 (void) printf("* Dimensions:\n");
399 (void) printf("* %d bytes/sector\n", 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);
419 }
420 exit(0);
421 }
422
423 /*
424 * display64 ()
425 *
426 * display64 contents of EFI partition without writing it to disk
427 */
428 static void
display64(struct dk_gpt * efi,char * device)429 display64(struct dk_gpt *efi, char *device)
430 {
431 int i;
432
433 /*
434 * Print out the VTOC
435 */
436 (void) printf("* %s default partition map\n", device);
437 (void) printf("*\n");
438 (void) printf("* Dimensions:\n");
439 (void) printf("* %d bytes/sector\n", efi->efi_lbasize);
440 (void) printf("* N/A sectors/track\n");
441 (void) printf("* N/A tracks/cylinder\n");
442 (void) printf("* N/A cylinders\n");
443 (void) printf("* N/A accessible cylinders\n");
444 (void) printf("*\n");
445 (void) printf("* Flags:\n");
446 (void) printf("* 1: unmountable\n");
447 (void) printf("* 10: read-only\n");
448 (void) printf("*\n");
449 (void) printf(
450 "\n* Partition Tag Flag First Sector Sector Count\n");
451 for (i = 0; i < efi->efi_nparts; i++) {
452 if (efi->efi_parts[i].p_size > 0)
453 (void) printf(
454 " %d %d 0%x %8lld %8lld\n",
455 i, efi->efi_parts[i].p_tag,
456 efi->efi_parts[i].p_flag,
457 efi->efi_parts[i].p_start,
458 efi->efi_parts[i].p_size);
459 }
460 exit(0);
461 }
462
463
464 /*
465 * insert()
466 *
467 * Insert a change into the VTOC.
468 */
469 static void
insert(char * data,struct extvtoc * vtoc)470 insert(char *data, struct extvtoc *vtoc)
471 {
472 int part;
473 int tag;
474 uint_t flag;
475 diskaddr_t start;
476 uint64_t size;
477
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);
482 }
483 if (part >= V_NUMPAR) {
484 (void) fprintf(stderr,
485 "Error in data \"%s\": No such partition %x\n",
486 data, part);
487 exit(1);
488 }
489 vtoc->v_part[part].p_tag = (ushort_t)tag;
490 vtoc->v_part[part].p_flag = (ushort_t)flag;
491 vtoc->v_part[part].p_start = start;
492 vtoc->v_part[part].p_size = size;
493 }
494
495 /*
496 * insert64()
497 *
498 * Insert a change into the VTOC.
499 */
500 static void
insert64(char * data,struct dk_gpt * efi)501 insert64(char *data, struct dk_gpt *efi)
502 {
503 int part;
504 int tag;
505 uint_t flag;
506 diskaddr_t start;
507 diskaddr_t size;
508
509 if (sscanf(data, "%d:%d:%x:%lld:%lld",
510 &part, &tag, &flag, &start, &size) != 5) {
511 (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data);
512 exit(1);
513 }
514 if (part >= efi->efi_nparts) {
515 (void) fprintf(stderr,
516 "Error in data \"%s\": No such partition %x\n",
517 data, part);
518 exit(1);
519 }
520 efi->efi_parts[part].p_tag = (ushort_t)tag;
521 efi->efi_parts[part].p_flag = (ushort_t)flag;
522 efi->efi_parts[part].p_start = start;
523 efi->efi_parts[part].p_size = size;
524 }
525
526 /*
527 * load()
528 *
529 * Load VTOC information from a datafile.
530 */
531 static void
load(FILE * fp,struct dk_geom * geom,struct extvtoc * vtoc)532 load(FILE *fp, struct dk_geom *geom, struct extvtoc *vtoc)
533 {
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;
543
544 for (i = 0; i < V_NUMPAR; ++i) {
545 vtoc->v_part[i].p_tag = 0;
546 vtoc->v_part[i].p_flag = V_UNMNT;
547 vtoc->v_part[i].p_start = 0;
548 vtoc->v_part[i].p_size = 0;
549 }
550 /*
551 * initialize partition 2, by convention it corresponds to whole
552 * disk. It will be overwritten, if specified in the input datafile
553 */
554 fullsz = (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;
559
560 nblks = geom->dkg_nsect * geom->dkg_nhead;
561
562 while (fgets(line, sizeof (line) - 1, fp)) {
563 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
564 continue;
565 line[strlen(line) - 1] = '\0';
566 if (sscanf(line, "%d %d %x %llu %llu",
567 &part, &tag, &flag, &start, &size) != 5) {
568 (void) fprintf(stderr, "Syntax error: \"%s\"\n",
569 line);
570 exit(1);
571 }
572 if (part >= V_NUMPAR) {
573 (void) fprintf(stderr,
574 "No such partition %x: \"%s\"\n",
575 part, line);
576 exit(1);
577 }
578 if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) {
579 (void) fprintf(stderr,
580 "Partition %d not aligned on cylinder boundary: \"%s\"\n",
581 part, line);
582 exit(1);
583 }
584 vtoc->v_part[part].p_tag = (ushort_t)tag;
585 vtoc->v_part[part].p_flag = (ushort_t)flag;
586 vtoc->v_part[part].p_start = start;
587 vtoc->v_part[part].p_size = size;
588 }
589 for (part = 0; part < V_NUMPAR; part++) {
590 vtoc->timestamp[part] = (time_t)0;
591 }
592 }
593
594 /*
595 * load64()
596 *
597 * Load VTOC information from a datafile.
598 */
599 static void
load64(FILE * fp,int fd,struct dk_gpt ** efi)600 load64(FILE *fp, int fd, struct dk_gpt **efi)
601 {
602 int part;
603 int tag;
604 uint_t flag;
605 diskaddr_t start;
606 diskaddr_t size;
607 int nlines = 0;
608 char line[256];
609 int i;
610 uint_t max_part = 0;
611 char **mem = NULL;
612
613 while (fgets(line, sizeof (line) - 1, fp)) {
614 if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
615 continue;
616 line[strlen(line) - 1] = '\0';
617 if (sscanf(line, "%d %d %x %lld %lld",
618 &part, &tag, &flag, &start, &size) != 5) {
619 (void) fprintf(stderr, "Syntax error: \"%s\"\n",
620 line);
621 exit(1);
622 }
623 mem = realloc(mem, sizeof (*mem) * (nlines + 1));
624 if (mem == NULL) {
625 (void) fprintf(stderr, "realloc failed\n");
626 exit(1);
627 }
628 mem[nlines] = strdup(line);
629 if (mem[nlines] == NULL) {
630 (void) fprintf(stderr, "strdup failed\n");
631 exit(1);
632 }
633 nlines++;
634 if (part > max_part)
635 max_part = part;
636 }
637 max_part++;
638
639 if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) {
640 (void) fprintf(stderr,
641 "efi_alloc_and_init failed: %d\n", i);
642 exit(1);
643 }
644 for (i = 0; i < (*efi)->efi_nparts; ++i) {
645 (*efi)->efi_parts[i].p_tag = V_UNASSIGNED;
646 (*efi)->efi_parts[i].p_flag = V_UNMNT;
647 (*efi)->efi_parts[i].p_start = 0;
648 (*efi)->efi_parts[i].p_size = 0;
649 }
650 lastlba = (*efi)->efi_last_u_lba;
651
652 for (i = 0; i < nlines; i++) {
653 if (sscanf(mem[i], "%d %d %x %lld %lld",
654 &part, &tag, &flag, &start, &size) != 5) {
655 (void) fprintf(stderr, "Syntax error: \"%s\"\n",
656 line);
657 exit(1);
658 }
659 free(mem[i]);
660 if (part >= (*efi)->efi_nparts) {
661 (void) fprintf(stderr,
662 "No such partition %x: \"%s\"\n",
663 part, line);
664 exit(1);
665 }
666 (*efi)->efi_parts[part].p_tag = (ushort_t)tag;
667 (*efi)->efi_parts[part].p_flag = (ushort_t)flag;
668 (*efi)->efi_parts[part].p_start = start;
669 (*efi)->efi_parts[part].p_size = size;
670 }
671 (*efi)->efi_nparts = max_part;
672 free(mem);
673 }
674
675
676 static void
usage()677 usage()
678 {
679 #if defined(sparc)
680 (void) fprintf(stderr,
681 "Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \
682 raw-device\n");
683
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");
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
validate(struct dk_geom * geom,struct extvtoc * vtoc)701 validate(struct dk_geom *geom, struct extvtoc *vtoc)
702 {
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;
712
713 nblks = geom->dkg_nsect * geom->dkg_nhead;
714
715 fullsz = (uint64_t)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 (vtoc->v_sectorsz == 0)
723 vtoc->v_sectorsz = sectsiz;
724 #endif /* defined(_SUNOS_VTOC_16) */
725
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
735 }
736 }
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);
744 }
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
756 }
757
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
781 }
782 }
783 }
784 }
785 }
786 }
787
788 /*
789 * validate64()
790 *
791 * Validate the new VTOC.
792 */
793 static void
validate64(struct dk_gpt * efi)794 validate64(struct dk_gpt *efi)
795 {
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;
805
806 fullsz = lastlba + 1;
807
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);
822 }
823
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
845 }
846 }
847 }
848 }
849 }
850 if (resv_part != 1) {
851 (void) fprintf(stderr,
852 "expected one reserved partition, but found %d\n",
853 resv_part);
854 exit(1);
855 }
856 }
857
858
859 /*
860 * Read the VTOC
861 */
862 int
vread(int fd,struct extvtoc * vtoc,char * devname)863 vread(int fd, struct extvtoc *vtoc, char *devname)
864 {
865 int i;
866
867 if ((i = read_extvtoc(fd, vtoc)) < 0) {
868 if (i == VT_ENOTSUP) {
869 return (1);
870 }
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);
877 }
878 exit(1);
879 }
880 return (0);
881 }
882
883 void
vread64(int fd,struct dk_gpt ** efi_hdr,char * devname)884 vread64(int fd, struct dk_gpt **efi_hdr, char *devname)
885 {
886 int i;
887
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);
898 }
899 lastlba = (*efi_hdr)->efi_last_u_lba;
900 }
901
902 /*
903 * Write the VTOC
904 */
905 void
vwrite(int fd,struct extvtoc * vtoc,char * devname)906 vwrite(int fd, struct extvtoc *vtoc, char *devname)
907 {
908 int i;
909
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);
918 }
919 exit(1);
920 }
921 }
922
923 /*
924 * Write the VTOC
925 */
926 void
vwrite64(int fd,struct dk_gpt * efi,char * devname)927 vwrite64(int fd, struct dk_gpt *efi, char *devname)
928 {
929 int i;
930
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);
939 }
940 exit(1);
941 }
942 }
943