xref: /titanic_51/usr/src/cmd/format/label.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * This file contains the code relating to label manipulation.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include "global.h"
34*7c478bd9Sstevel@tonic-gate #include "label.h"
35*7c478bd9Sstevel@tonic-gate #include "misc.h"
36*7c478bd9Sstevel@tonic-gate #include "main.h"
37*7c478bd9Sstevel@tonic-gate #include "partition.h"
38*7c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h"
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
41*7c478bd9Sstevel@tonic-gate #include <memory.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/uuid.h>
46*7c478bd9Sstevel@tonic-gate #include <errno.h>
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK)
49*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
50*7c478bd9Sstevel@tonic-gate #include "menu_fdisk.h"
51*7c478bd9Sstevel@tonic-gate #endif		/* defined(_FIRMWARE_NEEDS_FDISK) */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #ifndef	WD_NODE
54*7c478bd9Sstevel@tonic-gate #define	WD_NODE		7
55*7c478bd9Sstevel@tonic-gate #endif
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #ifdef	__STDC__
58*7c478bd9Sstevel@tonic-gate /*
59*7c478bd9Sstevel@tonic-gate  * Prototypes for ANSI C compilers
60*7c478bd9Sstevel@tonic-gate  */
61*7c478bd9Sstevel@tonic-gate static int	do_geometry_sanity_check(void);
62*7c478bd9Sstevel@tonic-gate static int	vtoc_to_label(struct dk_label *label, struct vtoc *vtoc,
63*7c478bd9Sstevel@tonic-gate 		struct dk_geom *geom);
64*7c478bd9Sstevel@tonic-gate extern int	read_vtoc(int, struct vtoc *);
65*7c478bd9Sstevel@tonic-gate extern int	write_vtoc(int, struct vtoc *);
66*7c478bd9Sstevel@tonic-gate static int	vtoc64_to_label(struct efi_info *, struct dk_gpt *);
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate #else	/* __STDC__ */
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate  * Prototypes for non-ANSI C compilers
72*7c478bd9Sstevel@tonic-gate  */
73*7c478bd9Sstevel@tonic-gate static int	do_geometry_sanity_check();
74*7c478bd9Sstevel@tonic-gate static int	vtoc_to_label();
75*7c478bd9Sstevel@tonic-gate extern int	read_vtoc();
76*7c478bd9Sstevel@tonic-gate extern int	write_vtoc();
77*7c478bd9Sstevel@tonic-gate static int	vtoc64_to_label();
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate #endif	/* __STDC__ */
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * This routine checks the given label to see if it is valid.
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate int
85*7c478bd9Sstevel@tonic-gate checklabel(label)
86*7c478bd9Sstevel@tonic-gate 	register struct dk_label *label;
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 	/*
90*7c478bd9Sstevel@tonic-gate 	 * Check the magic number.
91*7c478bd9Sstevel@tonic-gate 	 */
92*7c478bd9Sstevel@tonic-gate 	if (label->dkl_magic != DKL_MAGIC)
93*7c478bd9Sstevel@tonic-gate 		return (0);
94*7c478bd9Sstevel@tonic-gate 	/*
95*7c478bd9Sstevel@tonic-gate 	 * Check the checksum.
96*7c478bd9Sstevel@tonic-gate 	 */
97*7c478bd9Sstevel@tonic-gate 	if (checksum(label, CK_CHECKSUM) != 0)
98*7c478bd9Sstevel@tonic-gate 		return (0);
99*7c478bd9Sstevel@tonic-gate 	return (1);
100*7c478bd9Sstevel@tonic-gate }
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate /*
103*7c478bd9Sstevel@tonic-gate  * This routine checks or calculates the label checksum, depending on
104*7c478bd9Sstevel@tonic-gate  * the mode it is called in.
105*7c478bd9Sstevel@tonic-gate  */
106*7c478bd9Sstevel@tonic-gate int
107*7c478bd9Sstevel@tonic-gate checksum(label, mode)
108*7c478bd9Sstevel@tonic-gate 	struct	dk_label *label;
109*7c478bd9Sstevel@tonic-gate 	int	mode;
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	register short *sp, sum = 0;
112*7c478bd9Sstevel@tonic-gate 	register short count = (sizeof (struct dk_label)) / (sizeof (short));
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	/*
115*7c478bd9Sstevel@tonic-gate 	 * If we are generating a checksum, don't include the checksum
116*7c478bd9Sstevel@tonic-gate 	 * in the rolling xor.
117*7c478bd9Sstevel@tonic-gate 	 */
118*7c478bd9Sstevel@tonic-gate 	if (mode == CK_MAKESUM)
119*7c478bd9Sstevel@tonic-gate 		count -= 1;
120*7c478bd9Sstevel@tonic-gate 	sp = (short *)label;
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * Take the xor of all the half-words in the label.
123*7c478bd9Sstevel@tonic-gate 	 */
124*7c478bd9Sstevel@tonic-gate 	while (count--) {
125*7c478bd9Sstevel@tonic-gate 		sum ^= *sp++;
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	/*
128*7c478bd9Sstevel@tonic-gate 	 * If we are checking the checksum, the total will be zero for
129*7c478bd9Sstevel@tonic-gate 	 * a correct checksum, so we can just return the sum.
130*7c478bd9Sstevel@tonic-gate 	 */
131*7c478bd9Sstevel@tonic-gate 	if (mode == CK_CHECKSUM)
132*7c478bd9Sstevel@tonic-gate 		return (sum);
133*7c478bd9Sstevel@tonic-gate 	/*
134*7c478bd9Sstevel@tonic-gate 	 * If we are generating the checksum, fill it in.
135*7c478bd9Sstevel@tonic-gate 	 */
136*7c478bd9Sstevel@tonic-gate 	else {
137*7c478bd9Sstevel@tonic-gate 		label->dkl_cksum = sum;
138*7c478bd9Sstevel@tonic-gate 		return (0);
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate /*
143*7c478bd9Sstevel@tonic-gate  * This routine is used to extract the id string from the string stored
144*7c478bd9Sstevel@tonic-gate  * in a disk label.  The problem is that the string in the label has
145*7c478bd9Sstevel@tonic-gate  * the physical characteristics of the drive appended to it.  The approach
146*7c478bd9Sstevel@tonic-gate  * is to find the beginning of the physical attributes portion of the string
147*7c478bd9Sstevel@tonic-gate  * and truncate it there.
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate int
150*7c478bd9Sstevel@tonic-gate trim_id(id)
151*7c478bd9Sstevel@tonic-gate 	char	*id;
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate 	register char *c;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	/*
156*7c478bd9Sstevel@tonic-gate 	 * Start at the end of the string.  When we match the word ' cyl',
157*7c478bd9Sstevel@tonic-gate 	 * we are at the beginning of the attributes.
158*7c478bd9Sstevel@tonic-gate 	 */
159*7c478bd9Sstevel@tonic-gate 	for (c = id + strlen(id); c >= id; c--) {
160*7c478bd9Sstevel@tonic-gate 		if (strncmp(c, " cyl", strlen(" cyl")) == 0) {
161*7c478bd9Sstevel@tonic-gate 			/*
162*7c478bd9Sstevel@tonic-gate 			 * Remove any white space.
163*7c478bd9Sstevel@tonic-gate 			 */
164*7c478bd9Sstevel@tonic-gate 			for (; (((*(c - 1) == ' ') || (*(c - 1) == '\t')) &&
165*7c478bd9Sstevel@tonic-gate 				(c >= id)); c--);
166*7c478bd9Sstevel@tonic-gate 			break;
167*7c478bd9Sstevel@tonic-gate 		}
168*7c478bd9Sstevel@tonic-gate 	}
169*7c478bd9Sstevel@tonic-gate 	/*
170*7c478bd9Sstevel@tonic-gate 	 * If we ran off the beginning of the string, something is wrong.
171*7c478bd9Sstevel@tonic-gate 	 */
172*7c478bd9Sstevel@tonic-gate 	if (c < id)
173*7c478bd9Sstevel@tonic-gate 		return (-1);
174*7c478bd9Sstevel@tonic-gate 	/*
175*7c478bd9Sstevel@tonic-gate 	 * Truncate the string.
176*7c478bd9Sstevel@tonic-gate 	 */
177*7c478bd9Sstevel@tonic-gate 	*c = '\0';
178*7c478bd9Sstevel@tonic-gate 	return (0);
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate /*
182*7c478bd9Sstevel@tonic-gate  * This routine is used by write_label() to do a quick sanity check on the
183*7c478bd9Sstevel@tonic-gate  * supplied geometry. This is not a thorough check.
184*7c478bd9Sstevel@tonic-gate  *
185*7c478bd9Sstevel@tonic-gate  * The SCSI READ_CAPACITY command is used here to get the capacity of the
186*7c478bd9Sstevel@tonic-gate  * disk. But, the available area to store data on a disk is usually less
187*7c478bd9Sstevel@tonic-gate  * than this. So, if the specified geometry evaluates to a value which falls
188*7c478bd9Sstevel@tonic-gate  * in this margin, then such illegal geometries can slip through the cracks.
189*7c478bd9Sstevel@tonic-gate  */
190*7c478bd9Sstevel@tonic-gate static int
191*7c478bd9Sstevel@tonic-gate do_geometry_sanity_check()
192*7c478bd9Sstevel@tonic-gate {
193*7c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	 capacity;
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	if (uscsi_read_capacity(cur_file, &capacity)) {
196*7c478bd9Sstevel@tonic-gate 		err_print("Warning: Unable to get capacity."
197*7c478bd9Sstevel@tonic-gate 				" Cannot check geometry\n");
198*7c478bd9Sstevel@tonic-gate 		return (0);	/* Just ignore this problem */
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	if (capacity.sc_capacity < ncyl * nhead * nsect) {
202*7c478bd9Sstevel@tonic-gate 		err_print("\nWarning: Current geometry overshoots "
203*7c478bd9Sstevel@tonic-gate 				"actual geometry of disk\n\n");
204*7c478bd9Sstevel@tonic-gate 		if (check("Continue labelling disk") != 0)
205*7c478bd9Sstevel@tonic-gate 			return (-1);
206*7c478bd9Sstevel@tonic-gate 		return (0);	/* Just ignore this problem */
207*7c478bd9Sstevel@tonic-gate 	}
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	return (0);
210*7c478bd9Sstevel@tonic-gate }
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate /*
213*7c478bd9Sstevel@tonic-gate  * expand the internal 32-bit SMI VTOC into the 64-bit EFI version
214*7c478bd9Sstevel@tonic-gate  * for writing it out to the disk
215*7c478bd9Sstevel@tonic-gate  */
216*7c478bd9Sstevel@tonic-gate int
217*7c478bd9Sstevel@tonic-gate SMI_vtoc_to_EFI(int fd, struct dk_gpt **new_vtoc, struct vtoc *old_vtoc)
218*7c478bd9Sstevel@tonic-gate {
219*7c478bd9Sstevel@tonic-gate 	int i, j;
220*7c478bd9Sstevel@tonic-gate 	int vtoc_part_count = 0;
221*7c478bd9Sstevel@tonic-gate 	int highest_assigned_part = 0;
222*7c478bd9Sstevel@tonic-gate 	int last_par = 0;
223*7c478bd9Sstevel@tonic-gate 	int compact = 0;
224*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc;
225*7c478bd9Sstevel@tonic-gate 	struct vtoc	old_vtoc_copy;
226*7c478bd9Sstevel@tonic-gate 	diskaddr_t	start, size;
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_init(fd, EFI_NUMPAR, new_vtoc) != 0) {
229*7c478bd9Sstevel@tonic-gate 	    err_print("SMI vtoc to EFI failed\n");
230*7c478bd9Sstevel@tonic-gate 	    return (-1);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	vtoc = *new_vtoc;
233*7c478bd9Sstevel@tonic-gate 	old_vtoc_copy = *old_vtoc;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/*
236*7c478bd9Sstevel@tonic-gate 	 * Prepare old VTOC table for transfer by ensuring the
237*7c478bd9Sstevel@tonic-gate 	 * tags are set correctly.  Also collect information
238*7c478bd9Sstevel@tonic-gate 	 * about the old VTOC table including the number of
239*7c478bd9Sstevel@tonic-gate 	 * valid VTOC partitions and the highest VTOC partition
240*7c478bd9Sstevel@tonic-gate 	 * in use.  An EFI label provides fewer partitions, so
241*7c478bd9Sstevel@tonic-gate 	 * it is possible that the VTOC partitions cannot all be
242*7c478bd9Sstevel@tonic-gate 	 * transferred.
243*7c478bd9Sstevel@tonic-gate 	 */
244*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
245*7c478bd9Sstevel@tonic-gate 		/*
246*7c478bd9Sstevel@tonic-gate 		 * we may be carrying around old tags from the
247*7c478bd9Sstevel@tonic-gate 		 * default partition table.  If the partition
248*7c478bd9Sstevel@tonic-gate 		 * is really unassigned, set the tag correctly
249*7c478bd9Sstevel@tonic-gate 		 */
250*7c478bd9Sstevel@tonic-gate 		if ((old_vtoc->v_part[i].p_start == 0) &&
251*7c478bd9Sstevel@tonic-gate 		    (old_vtoc->v_part[i].p_size == 0))
252*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
253*7c478bd9Sstevel@tonic-gate 		/*
254*7c478bd9Sstevel@tonic-gate 		 * Likewise, if the partition is not empty, don't
255*7c478bd9Sstevel@tonic-gate 		 * write it out as "unassigned."
256*7c478bd9Sstevel@tonic-gate 		 */
257*7c478bd9Sstevel@tonic-gate 		if ((old_vtoc->v_part[i].p_size != 0) &&
258*7c478bd9Sstevel@tonic-gate 		    (old_vtoc->v_part[i].p_tag == V_UNASSIGNED))
259*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_ROOT;
260*7c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_BACKUP &&
261*7c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag != V_UNASSIGNED &&
262*7c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_start < vtoc->efi_first_u_lba) {
263*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_start = vtoc->efi_first_u_lba;
264*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size -= vtoc->efi_first_u_lba;
265*7c478bd9Sstevel@tonic-gate 		}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag == V_BACKUP ||
268*7c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag == V_BOOT) {
269*7c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
270*7c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_start =
271*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size = 0;
272*7c478bd9Sstevel@tonic-gate 		    last_par = i;
273*7c478bd9Sstevel@tonic-gate 		}
274*7c478bd9Sstevel@tonic-gate 		if ((i == WD_NODE) && (old_vtoc->v_part[i].p_tag !=
275*7c478bd9Sstevel@tonic-gate 		    V_UNASSIGNED)) {
276*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
277*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_start = 0;
278*7c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size = 0;
279*7c478bd9Sstevel@tonic-gate 		}
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_UNASSIGNED) {
282*7c478bd9Sstevel@tonic-gate 			/* Update count of valid VTOC partitions */
283*7c478bd9Sstevel@tonic-gate 			vtoc_part_count++;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 			/* Note the highest valid VTOC slice */
286*7c478bd9Sstevel@tonic-gate 			highest_assigned_part = i;
287*7c478bd9Sstevel@tonic-gate 		}
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 	if (vtoc_part_count > vtoc->efi_nparts - 1) {
290*7c478bd9Sstevel@tonic-gate 		/* Too many partitions to convert the VTOC label */
291*7c478bd9Sstevel@tonic-gate 		err_print("There are %d defined VTOC ", vtoc_part_count);
292*7c478bd9Sstevel@tonic-gate 		err_print("partitions and an EFI label\n");
293*7c478bd9Sstevel@tonic-gate 		err_print("can only accept %d.\n", vtoc->efi_nparts - 1);
294*7c478bd9Sstevel@tonic-gate 		if (check("Continue anyway") != 0) {
295*7c478bd9Sstevel@tonic-gate 			/* If no, restore VTOC and return an error */
296*7c478bd9Sstevel@tonic-gate 			*old_vtoc = old_vtoc_copy;
297*7c478bd9Sstevel@tonic-gate 			efi_free(vtoc);
298*7c478bd9Sstevel@tonic-gate 			return (-1);
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 	}
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (highest_assigned_part > vtoc->efi_nparts - 2) {
303*7c478bd9Sstevel@tonic-gate 		/*
304*7c478bd9Sstevel@tonic-gate 		 * Partition indexes cannot be transferred directly since
305*7c478bd9Sstevel@tonic-gate 		 * the highest valid VTOC index is higher than the highest
306*7c478bd9Sstevel@tonic-gate 		 * available EFI partition.  Ask the user if it is OK to
307*7c478bd9Sstevel@tonic-gate 		 * move the partitions to available slots
308*7c478bd9Sstevel@tonic-gate 		 */
309*7c478bd9Sstevel@tonic-gate 		err_print("VTOC partition %d is defined ",
310*7c478bd9Sstevel@tonic-gate 		    highest_assigned_part);
311*7c478bd9Sstevel@tonic-gate 		err_print("and the highest available EFI\n");
312*7c478bd9Sstevel@tonic-gate 		err_print("partition is %d.  The partitions\n",
313*7c478bd9Sstevel@tonic-gate 		    vtoc->efi_nparts - 2);
314*7c478bd9Sstevel@tonic-gate 		err_print("will fit if they are re-numbered\n");
315*7c478bd9Sstevel@tonic-gate 		if (check("OK to renumber") != 0) {
316*7c478bd9Sstevel@tonic-gate 			/* If no, restore VTOC and return an error */
317*7c478bd9Sstevel@tonic-gate 			*old_vtoc = old_vtoc_copy;
318*7c478bd9Sstevel@tonic-gate 			efi_free(vtoc);
319*7c478bd9Sstevel@tonic-gate 			return (-1);
320*7c478bd9Sstevel@tonic-gate 		} else {
321*7c478bd9Sstevel@tonic-gate 			compact = 1;
322*7c478bd9Sstevel@tonic-gate 		}
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	/*
326*7c478bd9Sstevel@tonic-gate 	 * Now copy the VTOC partitions, remapping the indices if
327*7c478bd9Sstevel@tonic-gate 	 * necessary.
328*7c478bd9Sstevel@tonic-gate 	 */
329*7c478bd9Sstevel@tonic-gate 	j = 0;
330*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
331*7c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_UNASSIGNED) {
332*7c478bd9Sstevel@tonic-gate 			/* Copy partition info */
333*7c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_tag = old_vtoc->v_part[i].p_tag;
334*7c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_flag = old_vtoc->v_part[i].p_flag;
335*7c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_start =
336*7c478bd9Sstevel@tonic-gate 			    old_vtoc->v_part[i].p_start;
337*7c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_size =
338*7c478bd9Sstevel@tonic-gate 			    old_vtoc->v_part[i].p_size;
339*7c478bd9Sstevel@tonic-gate 			if (vtoc->efi_parts[j].p_size != 0)
340*7c478bd9Sstevel@tonic-gate 				last_par = j;
341*7c478bd9Sstevel@tonic-gate 			j++; /* Increment EFI index */
342*7c478bd9Sstevel@tonic-gate 		} else {
343*7c478bd9Sstevel@tonic-gate 			if (!compact) {
344*7c478bd9Sstevel@tonic-gate 				j++; /* Increment EFI index */
345*7c478bd9Sstevel@tonic-gate 			}
346*7c478bd9Sstevel@tonic-gate 		}
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	start = vtoc->efi_parts[last_par].p_start;
350*7c478bd9Sstevel@tonic-gate 	size = vtoc->efi_parts[last_par].p_size;
351*7c478bd9Sstevel@tonic-gate 	if ((start + size) > (vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE)) {
352*7c478bd9Sstevel@tonic-gate 		size = (start + size) - (vtoc->efi_last_u_lba -
353*7c478bd9Sstevel@tonic-gate 			    EFI_MIN_RESV_SIZE);
354*7c478bd9Sstevel@tonic-gate 		vtoc->efi_parts[last_par].p_size -= size;
355*7c478bd9Sstevel@tonic-gate 	}
356*7c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
357*7c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
358*7c478bd9Sstevel@tonic-gate 	    vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE;
359*7c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	return (0);
362*7c478bd9Sstevel@tonic-gate }
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate /*
366*7c478bd9Sstevel@tonic-gate  * This routine constructs and writes a label on the disk.  It writes both
367*7c478bd9Sstevel@tonic-gate  * the primary and backup labels.  It assumes that there is a current
368*7c478bd9Sstevel@tonic-gate  * partition map already defined.  It also notifies the SunOS kernel of
369*7c478bd9Sstevel@tonic-gate  * the label and partition information it has written on the disk.
370*7c478bd9Sstevel@tonic-gate  */
371*7c478bd9Sstevel@tonic-gate int
372*7c478bd9Sstevel@tonic-gate write_label()
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	int	error = 0, head, sec;
375*7c478bd9Sstevel@tonic-gate 	struct dk_label label;
376*7c478bd9Sstevel@tonic-gate 	struct dk_label new_label;
377*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
378*7c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
379*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc64;
380*7c478bd9Sstevel@tonic-gate 	int		nbackups;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
383*7c478bd9Sstevel@tonic-gate 	int i;
384*7c478bd9Sstevel@tonic-gate #endif		/* defined(_SUNOS_VTOC_8) */
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	/*
387*7c478bd9Sstevel@tonic-gate 	 * If EFI label, then write it out to disk
388*7c478bd9Sstevel@tonic-gate 	 */
389*7c478bd9Sstevel@tonic-gate 	if (cur_label == L_TYPE_EFI) {
390*7c478bd9Sstevel@tonic-gate 	    enter_critical();
391*7c478bd9Sstevel@tonic-gate 	    vtoc64 = cur_parts->etoc;
392*7c478bd9Sstevel@tonic-gate 	    err_check(vtoc64);
393*7c478bd9Sstevel@tonic-gate 	    if (efi_write(cur_file, vtoc64) != 0) {
394*7c478bd9Sstevel@tonic-gate 		err_print("Warning: error writing EFI.\n");
395*7c478bd9Sstevel@tonic-gate 		error = -1;
396*7c478bd9Sstevel@tonic-gate 	    }
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	    cur_disk->disk_flags |= DSK_LABEL;
399*7c478bd9Sstevel@tonic-gate 	    exit_critical();
400*7c478bd9Sstevel@tonic-gate 	    return (error);
401*7c478bd9Sstevel@tonic-gate 	}
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	/*
404*7c478bd9Sstevel@tonic-gate 	 * Fill in a label structure with the geometry information.
405*7c478bd9Sstevel@tonic-gate 	 */
406*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)&label, 0, sizeof (struct dk_label));
407*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)&new_label, 0, sizeof (struct dk_label));
408*7c478bd9Sstevel@tonic-gate 	label.dkl_pcyl = pcyl;
409*7c478bd9Sstevel@tonic-gate 	label.dkl_ncyl = ncyl;
410*7c478bd9Sstevel@tonic-gate 	label.dkl_acyl = acyl;
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
413*7c478bd9Sstevel@tonic-gate 	label.dkl_bcyl = bcyl;
414*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOC_VTOC_16) */
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	label.dkl_nhead = nhead;
417*7c478bd9Sstevel@tonic-gate 	label.dkl_nsect = nsect;
418*7c478bd9Sstevel@tonic-gate 	label.dkl_apc = apc;
419*7c478bd9Sstevel@tonic-gate 	label.dkl_intrlv = 1;
420*7c478bd9Sstevel@tonic-gate 	label.dkl_rpm = cur_dtype->dtype_rpm;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
423*7c478bd9Sstevel@tonic-gate 	/*
424*7c478bd9Sstevel@tonic-gate 	 * Also fill in the current partition information.
425*7c478bd9Sstevel@tonic-gate 	 */
426*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
427*7c478bd9Sstevel@tonic-gate 		label.dkl_map[i] = cur_parts->pinfo_map[i];
428*7c478bd9Sstevel@tonic-gate 	}
429*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	label.dkl_magic = DKL_MAGIC;
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	/*
434*7c478bd9Sstevel@tonic-gate 	 * Fill in the vtoc information
435*7c478bd9Sstevel@tonic-gate 	 */
436*7c478bd9Sstevel@tonic-gate 	label.dkl_vtoc = cur_parts->vtoc;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 	/*
439*7c478bd9Sstevel@tonic-gate 	 * Use the current label
440*7c478bd9Sstevel@tonic-gate 	 */
441*7c478bd9Sstevel@tonic-gate 	bcopy(cur_disk->v_volume, label.dkl_vtoc.v_volume, LEN_DKL_VVOL);
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	/*
444*7c478bd9Sstevel@tonic-gate 	 * Put asciilabel in; on x86 it's in the vtoc, not the label.
445*7c478bd9Sstevel@tonic-gate 	 */
446*7c478bd9Sstevel@tonic-gate 	(void) snprintf(label.dkl_asciilabel, sizeof (label.dkl_asciilabel),
447*7c478bd9Sstevel@tonic-gate 	    "%s cyl %d alt %d hd %d sec %d",
448*7c478bd9Sstevel@tonic-gate 	    cur_dtype->dtype_asciilabel, ncyl, acyl, nhead, nsect);
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
451*7c478bd9Sstevel@tonic-gate 	/*
452*7c478bd9Sstevel@tonic-gate 	 * Also add in v_sectorsz, as the driver will.  Everyone
453*7c478bd9Sstevel@tonic-gate 	 * else is assuming DEV_BSIZE, so we do the same.
454*7c478bd9Sstevel@tonic-gate 	 */
455*7c478bd9Sstevel@tonic-gate 	label.dkl_vtoc.v_sectorsz = DEV_BSIZE;
456*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/*
459*7c478bd9Sstevel@tonic-gate 	 * Generate the correct checksum.
460*7c478bd9Sstevel@tonic-gate 	 */
461*7c478bd9Sstevel@tonic-gate 	(void) checksum(&label, CK_MAKESUM);
462*7c478bd9Sstevel@tonic-gate 	/*
463*7c478bd9Sstevel@tonic-gate 	 * Convert the label into a vtoc
464*7c478bd9Sstevel@tonic-gate 	 */
465*7c478bd9Sstevel@tonic-gate 	if (label_to_vtoc(&vtoc, &label) == -1) {
466*7c478bd9Sstevel@tonic-gate 		return (-1);
467*7c478bd9Sstevel@tonic-gate 	}
468*7c478bd9Sstevel@tonic-gate 	/*
469*7c478bd9Sstevel@tonic-gate 	 * Fill in the geometry info.  This is critical that
470*7c478bd9Sstevel@tonic-gate 	 * we do this before writing the vtoc.
471*7c478bd9Sstevel@tonic-gate 	 */
472*7c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&geom, sizeof (struct dk_geom));
473*7c478bd9Sstevel@tonic-gate 	geom.dkg_ncyl = ncyl;
474*7c478bd9Sstevel@tonic-gate 	geom.dkg_acyl = acyl;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
477*7c478bd9Sstevel@tonic-gate 	geom.dkg_bcyl = bcyl;
478*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	geom.dkg_nhead = nhead;
481*7c478bd9Sstevel@tonic-gate 	geom.dkg_nsect = nsect;
482*7c478bd9Sstevel@tonic-gate 	geom.dkg_intrlv = 1;
483*7c478bd9Sstevel@tonic-gate 	geom.dkg_apc = apc;
484*7c478bd9Sstevel@tonic-gate 	geom.dkg_rpm = cur_dtype->dtype_rpm;
485*7c478bd9Sstevel@tonic-gate 	geom.dkg_pcyl = pcyl;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	/*
488*7c478bd9Sstevel@tonic-gate 	 * Make a quick check to see that the geometry is being
489*7c478bd9Sstevel@tonic-gate 	 * written now is not way off from the actual capacity
490*7c478bd9Sstevel@tonic-gate 	 * of the disk. This is only an appoximate check and
491*7c478bd9Sstevel@tonic-gate 	 * is only for SCSI disks.
492*7c478bd9Sstevel@tonic-gate 	 */
493*7c478bd9Sstevel@tonic-gate 	if (SCSI && do_geometry_sanity_check() != 0) {
494*7c478bd9Sstevel@tonic-gate 		return (-1);
495*7c478bd9Sstevel@tonic-gate 	}
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	/*
498*7c478bd9Sstevel@tonic-gate 	 * Lock out interrupts so we do things in sync.
499*7c478bd9Sstevel@tonic-gate 	 */
500*7c478bd9Sstevel@tonic-gate 	enter_critical();
501*7c478bd9Sstevel@tonic-gate 	/*
502*7c478bd9Sstevel@tonic-gate 	 * Do the ioctl to tell the kernel the geometry.
503*7c478bd9Sstevel@tonic-gate 	 */
504*7c478bd9Sstevel@tonic-gate 	if (ioctl(cur_file, DKIOCSGEOM, &geom) == -1) {
505*7c478bd9Sstevel@tonic-gate 		err_print("Warning: error setting drive geometry.\n");
506*7c478bd9Sstevel@tonic-gate 		error = -1;
507*7c478bd9Sstevel@tonic-gate 	}
508*7c478bd9Sstevel@tonic-gate 	/*
509*7c478bd9Sstevel@tonic-gate 	 * Write the vtoc.  At the time of this writing, our
510*7c478bd9Sstevel@tonic-gate 	 * drivers convert the vtoc back to a label, and
511*7c478bd9Sstevel@tonic-gate 	 * then write both the primary and backup labels.
512*7c478bd9Sstevel@tonic-gate 	 * This is not a requirement, however, as we
513*7c478bd9Sstevel@tonic-gate 	 * always use an ioctl to read the vtoc from the
514*7c478bd9Sstevel@tonic-gate 	 * driver, so it can do as it likes.
515*7c478bd9Sstevel@tonic-gate 	 */
516*7c478bd9Sstevel@tonic-gate 	if (write_vtoc(cur_file, &vtoc) != 0) {
517*7c478bd9Sstevel@tonic-gate 		err_print("Warning: error writing VTOC.\n");
518*7c478bd9Sstevel@tonic-gate 		error = -1;
519*7c478bd9Sstevel@tonic-gate 	}
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 	/*
522*7c478bd9Sstevel@tonic-gate 	 * Calculate where the backup labels went.  They are always on
523*7c478bd9Sstevel@tonic-gate 	 * the last alternate cylinder, but some older drives put them
524*7c478bd9Sstevel@tonic-gate 	 * on head 2 instead of the last head.  They are always on the
525*7c478bd9Sstevel@tonic-gate 	 * first 5 odd sectors of the appropriate track.
526*7c478bd9Sstevel@tonic-gate 	 */
527*7c478bd9Sstevel@tonic-gate 	if (cur_ctype->ctype_flags & CF_BLABEL)
528*7c478bd9Sstevel@tonic-gate 		head  = 2;
529*7c478bd9Sstevel@tonic-gate 	else
530*7c478bd9Sstevel@tonic-gate 		head = nhead - 1;
531*7c478bd9Sstevel@tonic-gate 	/*
532*7c478bd9Sstevel@tonic-gate 	 * Read and verify the backup labels.
533*7c478bd9Sstevel@tonic-gate 	 */
534*7c478bd9Sstevel@tonic-gate 	nbackups = 0;
535*7c478bd9Sstevel@tonic-gate 	for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect));
536*7c478bd9Sstevel@tonic-gate 	    sec += 2) {
537*7c478bd9Sstevel@tonic-gate 		if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t)
538*7c478bd9Sstevel@tonic-gate 			((chs2bn(ncyl + acyl - 1, head, sec)) + solaris_offset),
539*7c478bd9Sstevel@tonic-gate 			1, (caddr_t)&new_label, F_NORMAL, NULL)) {
540*7c478bd9Sstevel@tonic-gate 			err_print("Warning: error reading backup label.\n");
541*7c478bd9Sstevel@tonic-gate 			error = -1;
542*7c478bd9Sstevel@tonic-gate 		} else {
543*7c478bd9Sstevel@tonic-gate 			if (bcmp((char *)&label, (char *)&new_label,
544*7c478bd9Sstevel@tonic-gate 				sizeof (struct dk_label)) == 0) {
545*7c478bd9Sstevel@tonic-gate 					nbackups++;
546*7c478bd9Sstevel@tonic-gate 			}
547*7c478bd9Sstevel@tonic-gate 		}
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 	if (nbackups != BAD_LISTCNT) {
550*7c478bd9Sstevel@tonic-gate 		err_print("Warning: %s\n", nbackups == 0 ?
551*7c478bd9Sstevel@tonic-gate 			"no backup labels" :
552*7c478bd9Sstevel@tonic-gate 			"some backup labels incorrect");
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate 	/*
555*7c478bd9Sstevel@tonic-gate 	 * Mark the current disk as labelled and notify the kernel of what
556*7c478bd9Sstevel@tonic-gate 	 * has happened.
557*7c478bd9Sstevel@tonic-gate 	 */
558*7c478bd9Sstevel@tonic-gate 	cur_disk->disk_flags |= DSK_LABEL;
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	exit_critical();
561*7c478bd9Sstevel@tonic-gate 	return (error);
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate /*
566*7c478bd9Sstevel@tonic-gate  * Read the label from the disk.
567*7c478bd9Sstevel@tonic-gate  * Do this via the read_vtoc() library routine, then convert it to a label.
568*7c478bd9Sstevel@tonic-gate  * We also need a DKIOCGGEOM ioctl to get the disk's geometry.
569*7c478bd9Sstevel@tonic-gate  */
570*7c478bd9Sstevel@tonic-gate int
571*7c478bd9Sstevel@tonic-gate read_label(int fd, struct dk_label *label)
572*7c478bd9Sstevel@tonic-gate {
573*7c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
574*7c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 	if (read_vtoc(fd, &vtoc) < 0 || ioctl(fd, DKIOCGGEOM, &geom) == -1) {
577*7c478bd9Sstevel@tonic-gate 		return (-1);
578*7c478bd9Sstevel@tonic-gate 	}
579*7c478bd9Sstevel@tonic-gate 	return (vtoc_to_label(label, &vtoc, &geom));
580*7c478bd9Sstevel@tonic-gate }
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate /*
583*7c478bd9Sstevel@tonic-gate  * Issue uscsi_inquiry and read_capacity commands to
584*7c478bd9Sstevel@tonic-gate  * retrieve the disk's Vendor, Product, Revision and
585*7c478bd9Sstevel@tonic-gate  * Capacity information.
586*7c478bd9Sstevel@tonic-gate  */
587*7c478bd9Sstevel@tonic-gate int
588*7c478bd9Sstevel@tonic-gate get_disk_info(int fd, struct efi_info *label)
589*7c478bd9Sstevel@tonic-gate {
590*7c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inquiry;
591*7c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	capacity;
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
594*7c478bd9Sstevel@tonic-gate 		err_print("Inquiry failed on %d\n", fd);
595*7c478bd9Sstevel@tonic-gate 		return (-1);
596*7c478bd9Sstevel@tonic-gate 	}
597*7c478bd9Sstevel@tonic-gate 	if (uscsi_read_capacity(fd, &capacity)) {
598*7c478bd9Sstevel@tonic-gate 		err_print("Read Capacity failed for %d\n", fd);
599*7c478bd9Sstevel@tonic-gate 		return (-1);
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->vendor, inquiry.inq_vid, 9);
603*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->product, inquiry.inq_pid, 17);
604*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->revision, inquiry.inq_revision, 5);
605*7c478bd9Sstevel@tonic-gate 	label->capacity = capacity.sc_capacity;
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	/* Since we are counting from zero, add 1 to capacity */
608*7c478bd9Sstevel@tonic-gate 	label->capacity++;
609*7c478bd9Sstevel@tonic-gate 	return (0);
610*7c478bd9Sstevel@tonic-gate }
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate int
613*7c478bd9Sstevel@tonic-gate read_efi_label(int fd, struct efi_info *label)
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc64;
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	/* This could fail if there is no label already */
618*7c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_read(fd, &vtoc64) < 0) {
619*7c478bd9Sstevel@tonic-gate 		return (-1);
620*7c478bd9Sstevel@tonic-gate 	}
621*7c478bd9Sstevel@tonic-gate 	if (vtoc64_to_label(label, vtoc64) != 0) {
622*7c478bd9Sstevel@tonic-gate 		err_print("vtoc64_to_label failed\n");
623*7c478bd9Sstevel@tonic-gate 		return (-1);
624*7c478bd9Sstevel@tonic-gate 	}
625*7c478bd9Sstevel@tonic-gate 	efi_free(vtoc64);
626*7c478bd9Sstevel@tonic-gate 	if (get_disk_info(fd, label) != 0) {
627*7c478bd9Sstevel@tonic-gate 		return (-1);
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 	return (0);
630*7c478bd9Sstevel@tonic-gate }
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate /*
634*7c478bd9Sstevel@tonic-gate  * We've read a 64-bit label which has no geometry information.  Use
635*7c478bd9Sstevel@tonic-gate  * some heuristics to fake up a geometry that would match the disk in
636*7c478bd9Sstevel@tonic-gate  * order to make the rest of format(1M) happy.
637*7c478bd9Sstevel@tonic-gate  */
638*7c478bd9Sstevel@tonic-gate static int
639*7c478bd9Sstevel@tonic-gate vtoc64_to_label(struct efi_info *label, struct dk_gpt *vtoc)
640*7c478bd9Sstevel@tonic-gate {
641*7c478bd9Sstevel@tonic-gate 	int		i, nparts = 0;
642*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*lmap;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct efi_info));
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	/* XXX do a sanity check here for nparts */
647*7c478bd9Sstevel@tonic-gate 	nparts = vtoc->efi_nparts;
648*7c478bd9Sstevel@tonic-gate 	lmap = (struct dk_gpt *) calloc(1, (sizeof (struct dk_part) *
649*7c478bd9Sstevel@tonic-gate 		    nparts) + sizeof (struct dk_gpt));
650*7c478bd9Sstevel@tonic-gate 	if (lmap == NULL) {
651*7c478bd9Sstevel@tonic-gate 		err_print("vtoc64_to_label: unable to allocate lmap\n");
652*7c478bd9Sstevel@tonic-gate 		fullabort();
653*7c478bd9Sstevel@tonic-gate 	}
654*7c478bd9Sstevel@tonic-gate 	label->e_parts = lmap;
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	/*
657*7c478bd9Sstevel@tonic-gate 	 * Copy necessary portions
658*7c478bd9Sstevel@tonic-gate 	 * XXX Maybe we can use memcpy() ??
659*7c478bd9Sstevel@tonic-gate 	 */
660*7c478bd9Sstevel@tonic-gate 	lmap->efi_version = vtoc->efi_version;
661*7c478bd9Sstevel@tonic-gate 	lmap->efi_nparts = vtoc->efi_nparts;
662*7c478bd9Sstevel@tonic-gate 	lmap->efi_part_size = vtoc->efi_part_size;
663*7c478bd9Sstevel@tonic-gate 	lmap->efi_lbasize = vtoc->efi_lbasize;
664*7c478bd9Sstevel@tonic-gate 	lmap->efi_last_lba = vtoc->efi_last_lba;
665*7c478bd9Sstevel@tonic-gate 	lmap->efi_first_u_lba = vtoc->efi_first_u_lba;
666*7c478bd9Sstevel@tonic-gate 	lmap->efi_last_u_lba = vtoc->efi_last_u_lba;
667*7c478bd9Sstevel@tonic-gate 	lmap->efi_flags = vtoc->efi_flags;
668*7c478bd9Sstevel@tonic-gate 	(void) memcpy((uchar_t *)&lmap->efi_disk_uguid,
669*7c478bd9Sstevel@tonic-gate 		(uchar_t *)&vtoc->efi_disk_uguid, sizeof (struct uuid));
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nparts; i++) {
672*7c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_tag = vtoc->efi_parts[i].p_tag;
673*7c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_flag = vtoc->efi_parts[i].p_flag;
674*7c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_start = vtoc->efi_parts[i].p_start;
675*7c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_size = vtoc->efi_parts[i].p_size;
676*7c478bd9Sstevel@tonic-gate 		(void) memcpy((uchar_t *)&lmap->efi_parts[i].p_uguid,
677*7c478bd9Sstevel@tonic-gate 		    (uchar_t *)&vtoc->efi_parts[i].p_uguid,
678*7c478bd9Sstevel@tonic-gate 		    sizeof (struct uuid));
679*7c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
680*7c478bd9Sstevel@tonic-gate 			bcopy(vtoc->efi_parts[i].p_name,
681*7c478bd9Sstevel@tonic-gate 			    lmap->efi_parts[i].p_name, LEN_DKL_VVOL);
682*7c478bd9Sstevel@tonic-gate 		}
683*7c478bd9Sstevel@tonic-gate 	}
684*7c478bd9Sstevel@tonic-gate 	return (0);
685*7c478bd9Sstevel@tonic-gate }
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate /*
688*7c478bd9Sstevel@tonic-gate  * Convert vtoc/geom to label.
689*7c478bd9Sstevel@tonic-gate  */
690*7c478bd9Sstevel@tonic-gate static int
691*7c478bd9Sstevel@tonic-gate vtoc_to_label(struct dk_label *label, struct vtoc *vtoc, struct dk_geom *geom)
692*7c478bd9Sstevel@tonic-gate {
693*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
694*7c478bd9Sstevel@tonic-gate 	struct dk_map32		*lmap;
695*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
696*7c478bd9Sstevel@tonic-gate 	struct dkl_partition	*lmap;
697*7c478bd9Sstevel@tonic-gate #else
698*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
699*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	struct partition	*vpart;
702*7c478bd9Sstevel@tonic-gate 	long			nblks;
703*7c478bd9Sstevel@tonic-gate 	int			i;
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	/*
708*7c478bd9Sstevel@tonic-gate 	 * Sanity-check the vtoc
709*7c478bd9Sstevel@tonic-gate 	 */
710*7c478bd9Sstevel@tonic-gate 	if (vtoc->v_sanity != VTOC_SANE || vtoc->v_sectorsz != DEV_BSIZE ||
711*7c478bd9Sstevel@tonic-gate 			vtoc->v_nparts != V_NUMPAR) {
712*7c478bd9Sstevel@tonic-gate 		return (-1);
713*7c478bd9Sstevel@tonic-gate 	}
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	/*
716*7c478bd9Sstevel@tonic-gate 	 * Sanity check of geometry
717*7c478bd9Sstevel@tonic-gate 	 */
718*7c478bd9Sstevel@tonic-gate 	if (geom->dkg_ncyl == 0 || geom->dkg_nhead == 0 ||
719*7c478bd9Sstevel@tonic-gate 			geom->dkg_nsect == 0) {
720*7c478bd9Sstevel@tonic-gate 		return (-1);
721*7c478bd9Sstevel@tonic-gate 	}
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	/*
726*7c478bd9Sstevel@tonic-gate 	 * Copy necessary portions of the geometry information
727*7c478bd9Sstevel@tonic-gate 	 */
728*7c478bd9Sstevel@tonic-gate 	label->dkl_rpm = geom->dkg_rpm;
729*7c478bd9Sstevel@tonic-gate 	label->dkl_pcyl = geom->dkg_pcyl;
730*7c478bd9Sstevel@tonic-gate 	label->dkl_apc = geom->dkg_apc;
731*7c478bd9Sstevel@tonic-gate 	label->dkl_intrlv = geom->dkg_intrlv;
732*7c478bd9Sstevel@tonic-gate 	label->dkl_ncyl = geom->dkg_ncyl;
733*7c478bd9Sstevel@tonic-gate 	label->dkl_acyl = geom->dkg_acyl;
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
736*7c478bd9Sstevel@tonic-gate 	label->dkl_bcyl = geom->dkg_bcyl;
737*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	label->dkl_nhead = geom->dkg_nhead;
740*7c478bd9Sstevel@tonic-gate 	label->dkl_nsect = geom->dkg_nsect;
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
743*7c478bd9Sstevel@tonic-gate 	label->dkl_obs1 = geom->dkg_obs1;
744*7c478bd9Sstevel@tonic-gate 	label->dkl_obs2 = geom->dkg_obs2;
745*7c478bd9Sstevel@tonic-gate 	label->dkl_obs3 = geom->dkg_obs3;
746*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 	label->dkl_write_reinstruct = geom->dkg_write_reinstruct;
749*7c478bd9Sstevel@tonic-gate 	label->dkl_read_reinstruct = geom->dkg_read_reinstruct;
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	/*
752*7c478bd9Sstevel@tonic-gate 	 * Copy vtoc structure fields into the disk label dk_vtoc
753*7c478bd9Sstevel@tonic-gate 	 */
754*7c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_sanity = vtoc->v_sanity;
755*7c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_nparts = vtoc->v_nparts;
756*7c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_version = vtoc->v_version;
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 	(void) memcpy(label->dkl_vtoc.v_volume, vtoc->v_volume,
759*7c478bd9Sstevel@tonic-gate 		LEN_DKL_VVOL);
760*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
761*7c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_tag = vtoc->v_part[i].p_tag;
762*7c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_flag = vtoc->v_part[i].p_flag;
763*7c478bd9Sstevel@tonic-gate 	}
764*7c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_bootinfo,
765*7c478bd9Sstevel@tonic-gate 		(char *)vtoc->v_bootinfo, sizeof (vtoc->v_bootinfo));
766*7c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_reserved,
767*7c478bd9Sstevel@tonic-gate 		(char *)vtoc->v_reserved, sizeof (vtoc->v_reserved));
768*7c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_timestamp,
769*7c478bd9Sstevel@tonic-gate 		(char *)vtoc->timestamp, sizeof (vtoc->timestamp));
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 	(void) memcpy(label->dkl_asciilabel, vtoc->v_asciilabel,
772*7c478bd9Sstevel@tonic-gate 		LEN_DKL_ASCII);
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate 	/*
775*7c478bd9Sstevel@tonic-gate 	 * Note the conversion from starting sector number
776*7c478bd9Sstevel@tonic-gate 	 * to starting cylinder number.
777*7c478bd9Sstevel@tonic-gate 	 * Return error if division results in a remainder.
778*7c478bd9Sstevel@tonic-gate 	 */
779*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
780*7c478bd9Sstevel@tonic-gate 	lmap = label->dkl_map;
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
783*7c478bd9Sstevel@tonic-gate 	lmap = label->dkl_vtoc.v_part;
784*7c478bd9Sstevel@tonic-gate #else
785*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
786*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	vpart = vtoc->v_part;
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 	nblks = (int)label->dkl_nsect * (int)label->dkl_nhead;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++, lmap++, vpart++) {
793*7c478bd9Sstevel@tonic-gate 		if ((vpart->p_start % nblks) != 0 ||
794*7c478bd9Sstevel@tonic-gate 				(vpart->p_size % nblks) != 0) {
795*7c478bd9Sstevel@tonic-gate 			return (-1);
796*7c478bd9Sstevel@tonic-gate 		}
797*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
798*7c478bd9Sstevel@tonic-gate 		lmap->dkl_cylno = vpart->p_start / nblks;
799*7c478bd9Sstevel@tonic-gate 		lmap->dkl_nblk = vpart->p_size;
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
802*7c478bd9Sstevel@tonic-gate 		lmap->p_start = vpart->p_start;
803*7c478bd9Sstevel@tonic-gate 		lmap->p_size = vpart->p_size;
804*7c478bd9Sstevel@tonic-gate #else
805*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
806*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
807*7c478bd9Sstevel@tonic-gate 	}
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 	/*
810*7c478bd9Sstevel@tonic-gate 	 * Finally, make a checksum
811*7c478bd9Sstevel@tonic-gate 	 */
812*7c478bd9Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 	return (0);
815*7c478bd9Sstevel@tonic-gate }
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate /*
820*7c478bd9Sstevel@tonic-gate  * Extract a vtoc structure out of a valid label
821*7c478bd9Sstevel@tonic-gate  */
822*7c478bd9Sstevel@tonic-gate int
823*7c478bd9Sstevel@tonic-gate label_to_vtoc(struct vtoc *vtoc, struct dk_label *label)
824*7c478bd9Sstevel@tonic-gate {
825*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
826*7c478bd9Sstevel@tonic-gate 	struct dk_map2		*lpart;
827*7c478bd9Sstevel@tonic-gate 	struct dk_map32		*lmap;
828*7c478bd9Sstevel@tonic-gate 	long			nblks;
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
831*7c478bd9Sstevel@tonic-gate 	struct dkl_partition	*lpart;
832*7c478bd9Sstevel@tonic-gate #else
833*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
834*7c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
835*7c478bd9Sstevel@tonic-gate 
836*7c478bd9Sstevel@tonic-gate 	struct partition	*vpart;
837*7c478bd9Sstevel@tonic-gate 	int			i;
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 	(void) memset((char *)vtoc, 0, sizeof (struct vtoc));
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	switch (label->dkl_vtoc.v_version) {
842*7c478bd9Sstevel@tonic-gate 	case 0:
843*7c478bd9Sstevel@tonic-gate 		/*
844*7c478bd9Sstevel@tonic-gate 		 * No valid vtoc information in the label.
845*7c478bd9Sstevel@tonic-gate 		 * Construct default p_flags and p_tags.
846*7c478bd9Sstevel@tonic-gate 		 */
847*7c478bd9Sstevel@tonic-gate 		vpart = vtoc->v_part;
848*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++, vpart++) {
849*7c478bd9Sstevel@tonic-gate 			vpart->p_tag = default_vtoc_map[i].p_tag;
850*7c478bd9Sstevel@tonic-gate 			vpart->p_flag = default_vtoc_map[i].p_flag;
851*7c478bd9Sstevel@tonic-gate 		}
852*7c478bd9Sstevel@tonic-gate 		break;
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	case V_VERSION:
855*7c478bd9Sstevel@tonic-gate 		vpart = vtoc->v_part;
856*7c478bd9Sstevel@tonic-gate 		lpart = label->dkl_vtoc.v_part;
857*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++, vpart++, lpart++) {
858*7c478bd9Sstevel@tonic-gate 			vpart->p_tag = lpart->p_tag;
859*7c478bd9Sstevel@tonic-gate 			vpart->p_flag = lpart->p_flag;
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
862*7c478bd9Sstevel@tonic-gate 			vpart->p_start = lpart->p_start;
863*7c478bd9Sstevel@tonic-gate 			vpart->p_size = lpart->p_size;
864*7c478bd9Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_16) */
865*7c478bd9Sstevel@tonic-gate 		}
866*7c478bd9Sstevel@tonic-gate 		(void) memcpy(vtoc->v_volume, label->dkl_vtoc.v_volume,
867*7c478bd9Sstevel@tonic-gate 			LEN_DKL_VVOL);
868*7c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->v_bootinfo,
869*7c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_bootinfo,
870*7c478bd9Sstevel@tonic-gate 				sizeof (vtoc->v_bootinfo));
871*7c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->v_reserved,
872*7c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_reserved,
873*7c478bd9Sstevel@tonic-gate 				sizeof (vtoc->v_reserved));
874*7c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->timestamp,
875*7c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_timestamp,
876*7c478bd9Sstevel@tonic-gate 				sizeof (vtoc->timestamp));
877*7c478bd9Sstevel@tonic-gate 		break;
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 	default:
880*7c478bd9Sstevel@tonic-gate 		return (-1);
881*7c478bd9Sstevel@tonic-gate 	}
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	/*
884*7c478bd9Sstevel@tonic-gate 	 * XXX - this looks wrong to me....
885*7c478bd9Sstevel@tonic-gate 	 * why are these values hardwired, rather than returned from
886*7c478bd9Sstevel@tonic-gate 	 * the real disk label?
887*7c478bd9Sstevel@tonic-gate 	 */
888*7c478bd9Sstevel@tonic-gate 	vtoc->v_sanity = VTOC_SANE;
889*7c478bd9Sstevel@tonic-gate 	vtoc->v_version = V_VERSION;
890*7c478bd9Sstevel@tonic-gate 	vtoc->v_sectorsz = DEV_BSIZE;
891*7c478bd9Sstevel@tonic-gate 	vtoc->v_nparts = V_NUMPAR;
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 	(void) memcpy(vtoc->v_asciilabel, label->dkl_asciilabel,
894*7c478bd9Sstevel@tonic-gate 		LEN_DKL_ASCII);
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
897*7c478bd9Sstevel@tonic-gate 	/*
898*7c478bd9Sstevel@tonic-gate 	 * Convert partitioning information.
899*7c478bd9Sstevel@tonic-gate 	 * Note the conversion from starting cylinder number
900*7c478bd9Sstevel@tonic-gate 	 * to starting sector number.
901*7c478bd9Sstevel@tonic-gate 	 */
902*7c478bd9Sstevel@tonic-gate 	lmap = label->dkl_map;
903*7c478bd9Sstevel@tonic-gate 	vpart = vtoc->v_part;
904*7c478bd9Sstevel@tonic-gate 	nblks = label->dkl_nsect * label->dkl_nhead;
905*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++, vpart++, lmap++) {
906*7c478bd9Sstevel@tonic-gate 		vpart->p_start = lmap->dkl_cylno * nblks;
907*7c478bd9Sstevel@tonic-gate 		vpart->p_size = lmap->dkl_nblk;
908*7c478bd9Sstevel@tonic-gate 	}
909*7c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate 	return (0);
912*7c478bd9Sstevel@tonic-gate }
913*7c478bd9Sstevel@tonic-gate 
914*7c478bd9Sstevel@tonic-gate /*
915*7c478bd9Sstevel@tonic-gate  * Input: File descriptor
916*7c478bd9Sstevel@tonic-gate  * Output: 1 if disk is >1TB OR has an EFI label, 0 otherwise.
917*7c478bd9Sstevel@tonic-gate  */
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate int
920*7c478bd9Sstevel@tonic-gate is_efi_type(int fd)
921*7c478bd9Sstevel@tonic-gate {
922*7c478bd9Sstevel@tonic-gate 	struct vtoc vtoc;
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1) {
925*7c478bd9Sstevel@tonic-gate 		if (errno == ENOTSUP) {
926*7c478bd9Sstevel@tonic-gate 			return (1);
927*7c478bd9Sstevel@tonic-gate 		}
928*7c478bd9Sstevel@tonic-gate 	}
929*7c478bd9Sstevel@tonic-gate 	return (0);
930*7c478bd9Sstevel@tonic-gate }
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate /* make sure the user specified something reasonable */
933*7c478bd9Sstevel@tonic-gate void
934*7c478bd9Sstevel@tonic-gate err_check(struct dk_gpt *vtoc)
935*7c478bd9Sstevel@tonic-gate {
936*7c478bd9Sstevel@tonic-gate 	int			resv_part = -1;
937*7c478bd9Sstevel@tonic-gate 	int			i, j;
938*7c478bd9Sstevel@tonic-gate 	diskaddr_t		istart, jstart, isize, jsize, endsect;
939*7c478bd9Sstevel@tonic-gate 	int			overlap = 0;
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate 	/*
942*7c478bd9Sstevel@tonic-gate 	 * make sure no partitions overlap
943*7c478bd9Sstevel@tonic-gate 	 */
944*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < vtoc->efi_nparts; i++) {
945*7c478bd9Sstevel@tonic-gate 		/* It can't be unassigned and have an actual size */
946*7c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
947*7c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_size != 0)) {
948*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
949*7c478bd9Sstevel@tonic-gate "partition %d is \"unassigned\" but has a size of %llu\n", i,
950*7c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[i].p_size);
951*7c478bd9Sstevel@tonic-gate 		}
952*7c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
953*7c478bd9Sstevel@tonic-gate 			continue;
954*7c478bd9Sstevel@tonic-gate 		}
955*7c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
956*7c478bd9Sstevel@tonic-gate 			if (resv_part != -1) {
957*7c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
958*7c478bd9Sstevel@tonic-gate "found duplicate reserved partition at %d\n",
959*7c478bd9Sstevel@tonic-gate 				i);
960*7c478bd9Sstevel@tonic-gate 			}
961*7c478bd9Sstevel@tonic-gate 			resv_part = i;
962*7c478bd9Sstevel@tonic-gate 			if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE)
963*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
964*7c478bd9Sstevel@tonic-gate "Warning: reserved partition size must be %d sectors\n",
965*7c478bd9Sstevel@tonic-gate 				EFI_MIN_RESV_SIZE);
966*7c478bd9Sstevel@tonic-gate 		}
967*7c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
968*7c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
969*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
970*7c478bd9Sstevel@tonic-gate 			    "Partition %d starts at %llu\n",
971*7c478bd9Sstevel@tonic-gate 			    i,
972*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_start);
973*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
974*7c478bd9Sstevel@tonic-gate 			    "It must be between %llu and %llu.\n",
975*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_first_u_lba,
976*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_last_u_lba);
977*7c478bd9Sstevel@tonic-gate 		}
978*7c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_start +
979*7c478bd9Sstevel@tonic-gate 		    vtoc->efi_parts[i].p_size <
980*7c478bd9Sstevel@tonic-gate 		    vtoc->efi_first_u_lba) ||
981*7c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_start +
982*7c478bd9Sstevel@tonic-gate 		    vtoc->efi_parts[i].p_size >
983*7c478bd9Sstevel@tonic-gate 		    vtoc->efi_last_u_lba + 1)) {
984*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
985*7c478bd9Sstevel@tonic-gate 			    "Partition %d ends at %llu\n",
986*7c478bd9Sstevel@tonic-gate 			    i,
987*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_start +
988*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_size);
989*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
990*7c478bd9Sstevel@tonic-gate 			    "It must be between %llu and %llu.\n",
991*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_first_u_lba,
992*7c478bd9Sstevel@tonic-gate 			    vtoc->efi_last_u_lba);
993*7c478bd9Sstevel@tonic-gate 		}
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < vtoc->efi_nparts; j++) {
996*7c478bd9Sstevel@tonic-gate 			isize = vtoc->efi_parts[i].p_size;
997*7c478bd9Sstevel@tonic-gate 			jsize = vtoc->efi_parts[j].p_size;
998*7c478bd9Sstevel@tonic-gate 			istart = vtoc->efi_parts[i].p_start;
999*7c478bd9Sstevel@tonic-gate 			jstart = vtoc->efi_parts[j].p_start;
1000*7c478bd9Sstevel@tonic-gate 			if ((i != j) && (isize != 0) && (jsize != 0)) {
1001*7c478bd9Sstevel@tonic-gate 				endsect = jstart + jsize -1;
1002*7c478bd9Sstevel@tonic-gate 				if ((jstart <= istart) &&
1003*7c478bd9Sstevel@tonic-gate 				    (istart <= endsect)) {
1004*7c478bd9Sstevel@tonic-gate 					if (!overlap) {
1005*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
1006*7c478bd9Sstevel@tonic-gate "label error: EFI Labels do not support overlapping partitions\n");
1007*7c478bd9Sstevel@tonic-gate 					}
1008*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
1009*7c478bd9Sstevel@tonic-gate "Partition %d overlaps partition %d.\n", i, j);
1010*7c478bd9Sstevel@tonic-gate 					overlap = 1;
1011*7c478bd9Sstevel@tonic-gate 				}
1012*7c478bd9Sstevel@tonic-gate 			}
1013*7c478bd9Sstevel@tonic-gate 		}
1014*7c478bd9Sstevel@tonic-gate 	}
1015*7c478bd9Sstevel@tonic-gate 	/* make sure there is a reserved partition */
1016*7c478bd9Sstevel@tonic-gate 	if (resv_part == -1) {
1017*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1018*7c478bd9Sstevel@tonic-gate 			"no reserved partition found\n");
1019*7c478bd9Sstevel@tonic-gate 	}
1020*7c478bd9Sstevel@tonic-gate }
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate #ifdef	FOR_DEBUGGING_ONLY
1023*7c478bd9Sstevel@tonic-gate int
1024*7c478bd9Sstevel@tonic-gate dump_label(label)
1025*7c478bd9Sstevel@tonic-gate 	struct dk_label	*label;
1026*7c478bd9Sstevel@tonic-gate {
1027*7c478bd9Sstevel@tonic-gate 	int		i;
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	fmt_print("%s\n", label->dkl_asciilabel);
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 	fmt_print("version:  %d\n", label->dkl_vtoc.v_version);
1032*7c478bd9Sstevel@tonic-gate 	fmt_print("volume:   ");
1033*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LEN_DKL_VVOL; i++) {
1034*7c478bd9Sstevel@tonic-gate 		if (label->dkl_vtoc.v_volume[i] == 0)
1035*7c478bd9Sstevel@tonic-gate 			break;
1036*7c478bd9Sstevel@tonic-gate 		fmt_print("%c", label->dkl_vtoc.v_volume[i]);
1037*7c478bd9Sstevel@tonic-gate 	}
1038*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
1039*7c478bd9Sstevel@tonic-gate 	fmt_print("v_nparts: %d\n", label->dkl_vtoc.v_nparts);
1040*7c478bd9Sstevel@tonic-gate 	fmt_print("v_sanity: %lx\n", label->dkl_vtoc.v_sanity);
1041*7c478bd9Sstevel@tonic-gate 
1042*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
1043*7c478bd9Sstevel@tonic-gate 	fmt_print("rpm:      %d\n", label->dkl_rpm);
1044*7c478bd9Sstevel@tonic-gate 	fmt_print("pcyl:     %d\n", label->dkl_pcyl);
1045*7c478bd9Sstevel@tonic-gate 	fmt_print("apc:      %d\n", label->dkl_apc);
1046*7c478bd9Sstevel@tonic-gate 	fmt_print("obs1:     %d\n", label->dkl_obs1);
1047*7c478bd9Sstevel@tonic-gate 	fmt_print("obs2:     %d\n", label->dkl_obs2);
1048*7c478bd9Sstevel@tonic-gate 	fmt_print("intrlv:   %d\n", label->dkl_intrlv);
1049*7c478bd9Sstevel@tonic-gate 	fmt_print("ncyl:     %d\n", label->dkl_ncyl);
1050*7c478bd9Sstevel@tonic-gate 	fmt_print("acyl:     %d\n", label->dkl_acyl);
1051*7c478bd9Sstevel@tonic-gate 	fmt_print("nhead:    %d\n", label->dkl_nhead);
1052*7c478bd9Sstevel@tonic-gate 	fmt_print("nsect:    %d\n", label->dkl_nsect);
1053*7c478bd9Sstevel@tonic-gate 	fmt_print("obs3:     %d\n", label->dkl_obs3);
1054*7c478bd9Sstevel@tonic-gate 	fmt_print("obs4:     %d\n", label->dkl_obs4);
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
1057*7c478bd9Sstevel@tonic-gate 	fmt_print("rpm:      %d\n", label->dkl_rpm);
1058*7c478bd9Sstevel@tonic-gate 	fmt_print("pcyl:     %d\n", label->dkl_pcyl);
1059*7c478bd9Sstevel@tonic-gate 	fmt_print("apc:      %d\n", label->dkl_apc);
1060*7c478bd9Sstevel@tonic-gate 	fmt_print("intrlv:   %d\n", label->dkl_intrlv);
1061*7c478bd9Sstevel@tonic-gate 	fmt_print("ncyl:     %d\n", label->dkl_ncyl);
1062*7c478bd9Sstevel@tonic-gate 	fmt_print("acyl:     %d\n", label->dkl_acyl);
1063*7c478bd9Sstevel@tonic-gate 	fmt_print("nhead:    %d\n", label->dkl_nhead);
1064*7c478bd9Sstevel@tonic-gate 	fmt_print("nsect:    %d\n", label->dkl_nsect);
1065*7c478bd9Sstevel@tonic-gate 	fmt_print("bcyl:     %d\n", label->dkl_bcyl);
1066*7c478bd9Sstevel@tonic-gate 	fmt_print("skew:     %d\n", label->dkl_skew);
1067*7c478bd9Sstevel@tonic-gate #else
1068*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
1069*7c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
1070*7c478bd9Sstevel@tonic-gate 	fmt_print("magic:    %0x\n", label->dkl_magic);
1071*7c478bd9Sstevel@tonic-gate 	fmt_print("cksum:    %0x\n", label->dkl_cksum);
1072*7c478bd9Sstevel@tonic-gate 
1073*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
1076*7c478bd9Sstevel@tonic-gate 		fmt_print("%c:        cyl=%d, blocks=%d", i+'a',
1077*7c478bd9Sstevel@tonic-gate 			label->dkl_map[i].dkl_cylno,
1078*7c478bd9Sstevel@tonic-gate 			label->dkl_map[i].dkl_nblk);
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
1081*7c478bd9Sstevel@tonic-gate 		fmt_print("%c:        start=%d, blocks=%d", i+'a',
1082*7c478bd9Sstevel@tonic-gate 		    label->dkl_vtoc.v_part[i].p_start,
1083*7c478bd9Sstevel@tonic-gate 		    label->dkl_vtoc.v_part[i].p_size);
1084*7c478bd9Sstevel@tonic-gate #else
1085*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
1086*7c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
1087*7c478bd9Sstevel@tonic-gate 
1088*7c478bd9Sstevel@tonic-gate 		fmt_print(",  tag=%d,  flag=%d",
1089*7c478bd9Sstevel@tonic-gate 			label->dkl_vtoc.v_part[i].p_tag,
1090*7c478bd9Sstevel@tonic-gate 			label->dkl_vtoc.v_part[i].p_flag);
1091*7c478bd9Sstevel@tonic-gate 		fmt_print("\n");
1092*7c478bd9Sstevel@tonic-gate 	}
1093*7c478bd9Sstevel@tonic-gate 
1094*7c478bd9Sstevel@tonic-gate 	fmt_print("read_reinstruct:  %d\n", label->dkl_read_reinstruct);
1095*7c478bd9Sstevel@tonic-gate 	fmt_print("write_reinstruct: %d\n", label->dkl_write_reinstruct);
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	fmt_print("bootinfo: ");
1098*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
1099*7c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_bootinfo[i]);
1100*7c478bd9Sstevel@tonic-gate 	}
1101*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
1102*7c478bd9Sstevel@tonic-gate 
1103*7c478bd9Sstevel@tonic-gate 	fmt_print("reserved: ");
1104*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 10; i++) {
1105*7c478bd9Sstevel@tonic-gate 		if ((i % 4) == 3)
1106*7c478bd9Sstevel@tonic-gate 			fmt_print("\n");
1107*7c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_reserved[i]);
1108*7c478bd9Sstevel@tonic-gate 	}
1109*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
1110*7c478bd9Sstevel@tonic-gate 
1111*7c478bd9Sstevel@tonic-gate 	fmt_print("timestamp:\n");
1112*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
1113*7c478bd9Sstevel@tonic-gate 		if ((i % 4) == 3)
1114*7c478bd9Sstevel@tonic-gate 			fmt_print("\n");
1115*7c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_timestamp[i]);
1116*7c478bd9Sstevel@tonic-gate 	}
1117*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
1118*7c478bd9Sstevel@tonic-gate 
1119*7c478bd9Sstevel@tonic-gate 	fmt_print("pad:\n");
1120*7c478bd9Sstevel@tonic-gate 	dump("", label->dkl_pad, LEN_DKL_PAD, HEX_ONLY);
1121*7c478bd9Sstevel@tonic-gate 
1122*7c478bd9Sstevel@tonic-gate 	fmt_print("\n\n");
1123*7c478bd9Sstevel@tonic-gate }
1124*7c478bd9Sstevel@tonic-gate #endif	/* FOR_DEBUGGING_ONLY */
1125