xref: /titanic_44/usr/src/cmd/format/label.c (revision 3ccda6479cf240cd732ac4b7a8a82fcc1716496d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * This file contains the code relating to label manipulation.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "global.h"
347c478bd9Sstevel@tonic-gate #include "label.h"
357c478bd9Sstevel@tonic-gate #include "misc.h"
367c478bd9Sstevel@tonic-gate #include "main.h"
377c478bd9Sstevel@tonic-gate #include "partition.h"
387c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h"
397c478bd9Sstevel@tonic-gate #include <string.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <memory.h>
427c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
437c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
447c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
457c478bd9Sstevel@tonic-gate #include <sys/uuid.h>
467c478bd9Sstevel@tonic-gate #include <errno.h>
47*3ccda647Slclee #include <devid.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK)
507c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
517c478bd9Sstevel@tonic-gate #include "menu_fdisk.h"
527c478bd9Sstevel@tonic-gate #endif		/* defined(_FIRMWARE_NEEDS_FDISK) */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #ifndef	WD_NODE
557c478bd9Sstevel@tonic-gate #define	WD_NODE		7
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #ifdef	__STDC__
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * Prototypes for ANSI C compilers
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate static int	do_geometry_sanity_check(void);
637c478bd9Sstevel@tonic-gate static int	vtoc_to_label(struct dk_label *label, struct vtoc *vtoc,
647c478bd9Sstevel@tonic-gate 		struct dk_geom *geom);
657c478bd9Sstevel@tonic-gate extern int	read_vtoc(int, struct vtoc *);
667c478bd9Sstevel@tonic-gate extern int	write_vtoc(int, struct vtoc *);
677c478bd9Sstevel@tonic-gate static int	vtoc64_to_label(struct efi_info *, struct dk_gpt *);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #else	/* __STDC__ */
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * Prototypes for non-ANSI C compilers
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate static int	do_geometry_sanity_check();
757c478bd9Sstevel@tonic-gate static int	vtoc_to_label();
767c478bd9Sstevel@tonic-gate extern int	read_vtoc();
777c478bd9Sstevel@tonic-gate extern int	write_vtoc();
787c478bd9Sstevel@tonic-gate static int	vtoc64_to_label();
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #endif	/* __STDC__ */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * This routine checks the given label to see if it is valid.
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate int
867c478bd9Sstevel@tonic-gate checklabel(label)
877c478bd9Sstevel@tonic-gate 	register struct dk_label *label;
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	/*
917c478bd9Sstevel@tonic-gate 	 * Check the magic number.
927c478bd9Sstevel@tonic-gate 	 */
937c478bd9Sstevel@tonic-gate 	if (label->dkl_magic != DKL_MAGIC)
947c478bd9Sstevel@tonic-gate 		return (0);
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * Check the checksum.
977c478bd9Sstevel@tonic-gate 	 */
987c478bd9Sstevel@tonic-gate 	if (checksum(label, CK_CHECKSUM) != 0)
997c478bd9Sstevel@tonic-gate 		return (0);
1007c478bd9Sstevel@tonic-gate 	return (1);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * This routine checks or calculates the label checksum, depending on
1057c478bd9Sstevel@tonic-gate  * the mode it is called in.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate int
1087c478bd9Sstevel@tonic-gate checksum(label, mode)
1097c478bd9Sstevel@tonic-gate 	struct	dk_label *label;
1107c478bd9Sstevel@tonic-gate 	int	mode;
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	register short *sp, sum = 0;
1137c478bd9Sstevel@tonic-gate 	register short count = (sizeof (struct dk_label)) / (sizeof (short));
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/*
1167c478bd9Sstevel@tonic-gate 	 * If we are generating a checksum, don't include the checksum
1177c478bd9Sstevel@tonic-gate 	 * in the rolling xor.
1187c478bd9Sstevel@tonic-gate 	 */
1197c478bd9Sstevel@tonic-gate 	if (mode == CK_MAKESUM)
1207c478bd9Sstevel@tonic-gate 		count -= 1;
1217c478bd9Sstevel@tonic-gate 	sp = (short *)label;
1227c478bd9Sstevel@tonic-gate 	/*
1237c478bd9Sstevel@tonic-gate 	 * Take the xor of all the half-words in the label.
1247c478bd9Sstevel@tonic-gate 	 */
1257c478bd9Sstevel@tonic-gate 	while (count--) {
1267c478bd9Sstevel@tonic-gate 		sum ^= *sp++;
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 	/*
1297c478bd9Sstevel@tonic-gate 	 * If we are checking the checksum, the total will be zero for
1307c478bd9Sstevel@tonic-gate 	 * a correct checksum, so we can just return the sum.
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate 	if (mode == CK_CHECKSUM)
1337c478bd9Sstevel@tonic-gate 		return (sum);
1347c478bd9Sstevel@tonic-gate 	/*
1357c478bd9Sstevel@tonic-gate 	 * If we are generating the checksum, fill it in.
1367c478bd9Sstevel@tonic-gate 	 */
1377c478bd9Sstevel@tonic-gate 	else {
1387c478bd9Sstevel@tonic-gate 		label->dkl_cksum = sum;
1397c478bd9Sstevel@tonic-gate 		return (0);
1407c478bd9Sstevel@tonic-gate 	}
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate  * This routine is used to extract the id string from the string stored
1457c478bd9Sstevel@tonic-gate  * in a disk label.  The problem is that the string in the label has
1467c478bd9Sstevel@tonic-gate  * the physical characteristics of the drive appended to it.  The approach
1477c478bd9Sstevel@tonic-gate  * is to find the beginning of the physical attributes portion of the string
1487c478bd9Sstevel@tonic-gate  * and truncate it there.
1497c478bd9Sstevel@tonic-gate  */
1507c478bd9Sstevel@tonic-gate int
1517c478bd9Sstevel@tonic-gate trim_id(id)
1527c478bd9Sstevel@tonic-gate 	char	*id;
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	register char *c;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * Start at the end of the string.  When we match the word ' cyl',
1587c478bd9Sstevel@tonic-gate 	 * we are at the beginning of the attributes.
1597c478bd9Sstevel@tonic-gate 	 */
1607c478bd9Sstevel@tonic-gate 	for (c = id + strlen(id); c >= id; c--) {
1617c478bd9Sstevel@tonic-gate 		if (strncmp(c, " cyl", strlen(" cyl")) == 0) {
1627c478bd9Sstevel@tonic-gate 			/*
1637c478bd9Sstevel@tonic-gate 			 * Remove any white space.
1647c478bd9Sstevel@tonic-gate 			 */
1657c478bd9Sstevel@tonic-gate 			for (; (((*(c - 1) == ' ') || (*(c - 1) == '\t')) &&
1667c478bd9Sstevel@tonic-gate 				(c >= id)); c--);
1677c478bd9Sstevel@tonic-gate 			break;
1687c478bd9Sstevel@tonic-gate 		}
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	/*
1717c478bd9Sstevel@tonic-gate 	 * If we ran off the beginning of the string, something is wrong.
1727c478bd9Sstevel@tonic-gate 	 */
1737c478bd9Sstevel@tonic-gate 	if (c < id)
1747c478bd9Sstevel@tonic-gate 		return (-1);
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Truncate the string.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	*c = '\0';
1797c478bd9Sstevel@tonic-gate 	return (0);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  * This routine is used by write_label() to do a quick sanity check on the
1847c478bd9Sstevel@tonic-gate  * supplied geometry. This is not a thorough check.
1857c478bd9Sstevel@tonic-gate  *
1867c478bd9Sstevel@tonic-gate  * The SCSI READ_CAPACITY command is used here to get the capacity of the
1877c478bd9Sstevel@tonic-gate  * disk. But, the available area to store data on a disk is usually less
1887c478bd9Sstevel@tonic-gate  * than this. So, if the specified geometry evaluates to a value which falls
1897c478bd9Sstevel@tonic-gate  * in this margin, then such illegal geometries can slip through the cracks.
1907c478bd9Sstevel@tonic-gate  */
1917c478bd9Sstevel@tonic-gate static int
1927c478bd9Sstevel@tonic-gate do_geometry_sanity_check()
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	 capacity;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	if (uscsi_read_capacity(cur_file, &capacity)) {
1977c478bd9Sstevel@tonic-gate 		err_print("Warning: Unable to get capacity."
1987c478bd9Sstevel@tonic-gate 				" Cannot check geometry\n");
1997c478bd9Sstevel@tonic-gate 		return (0);	/* Just ignore this problem */
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	if (capacity.sc_capacity < ncyl * nhead * nsect) {
2037c478bd9Sstevel@tonic-gate 		err_print("\nWarning: Current geometry overshoots "
2047c478bd9Sstevel@tonic-gate 				"actual geometry of disk\n\n");
2057c478bd9Sstevel@tonic-gate 		if (check("Continue labelling disk") != 0)
2067c478bd9Sstevel@tonic-gate 			return (-1);
2077c478bd9Sstevel@tonic-gate 		return (0);	/* Just ignore this problem */
2087c478bd9Sstevel@tonic-gate 	}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	return (0);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * expand the internal 32-bit SMI VTOC into the 64-bit EFI version
2157c478bd9Sstevel@tonic-gate  * for writing it out to the disk
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate int
2187c478bd9Sstevel@tonic-gate SMI_vtoc_to_EFI(int fd, struct dk_gpt **new_vtoc, struct vtoc *old_vtoc)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	int i, j;
2217c478bd9Sstevel@tonic-gate 	int vtoc_part_count = 0;
2227c478bd9Sstevel@tonic-gate 	int highest_assigned_part = 0;
2237c478bd9Sstevel@tonic-gate 	int last_par = 0;
2247c478bd9Sstevel@tonic-gate 	int compact = 0;
2257c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc;
2267c478bd9Sstevel@tonic-gate 	struct vtoc	old_vtoc_copy;
2277c478bd9Sstevel@tonic-gate 	diskaddr_t	start, size;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_init(fd, EFI_NUMPAR, new_vtoc) != 0) {
2307c478bd9Sstevel@tonic-gate 	    err_print("SMI vtoc to EFI failed\n");
2317c478bd9Sstevel@tonic-gate 	    return (-1);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	vtoc = *new_vtoc;
2347c478bd9Sstevel@tonic-gate 	old_vtoc_copy = *old_vtoc;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/*
2377c478bd9Sstevel@tonic-gate 	 * Prepare old VTOC table for transfer by ensuring the
2387c478bd9Sstevel@tonic-gate 	 * tags are set correctly.  Also collect information
2397c478bd9Sstevel@tonic-gate 	 * about the old VTOC table including the number of
2407c478bd9Sstevel@tonic-gate 	 * valid VTOC partitions and the highest VTOC partition
2417c478bd9Sstevel@tonic-gate 	 * in use.  An EFI label provides fewer partitions, so
2427c478bd9Sstevel@tonic-gate 	 * it is possible that the VTOC partitions cannot all be
2437c478bd9Sstevel@tonic-gate 	 * transferred.
2447c478bd9Sstevel@tonic-gate 	 */
2457c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
2467c478bd9Sstevel@tonic-gate 		/*
2477c478bd9Sstevel@tonic-gate 		 * we may be carrying around old tags from the
2487c478bd9Sstevel@tonic-gate 		 * default partition table.  If the partition
2497c478bd9Sstevel@tonic-gate 		 * is really unassigned, set the tag correctly
2507c478bd9Sstevel@tonic-gate 		 */
2517c478bd9Sstevel@tonic-gate 		if ((old_vtoc->v_part[i].p_start == 0) &&
2527c478bd9Sstevel@tonic-gate 		    (old_vtoc->v_part[i].p_size == 0))
2537c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
2547c478bd9Sstevel@tonic-gate 		/*
2557c478bd9Sstevel@tonic-gate 		 * Likewise, if the partition is not empty, don't
2567c478bd9Sstevel@tonic-gate 		 * write it out as "unassigned."
2577c478bd9Sstevel@tonic-gate 		 */
2587c478bd9Sstevel@tonic-gate 		if ((old_vtoc->v_part[i].p_size != 0) &&
2597c478bd9Sstevel@tonic-gate 		    (old_vtoc->v_part[i].p_tag == V_UNASSIGNED))
2607c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_ROOT;
2617c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_BACKUP &&
2627c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag != V_UNASSIGNED &&
2637c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_start < vtoc->efi_first_u_lba) {
2647c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_start = vtoc->efi_first_u_lba;
2657c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size -= vtoc->efi_first_u_lba;
2667c478bd9Sstevel@tonic-gate 		}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag == V_BACKUP ||
2697c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag == V_BOOT) {
2707c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
2717c478bd9Sstevel@tonic-gate 		    old_vtoc->v_part[i].p_start =
2727c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size = 0;
2737c478bd9Sstevel@tonic-gate 		    last_par = i;
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 		if ((i == WD_NODE) && (old_vtoc->v_part[i].p_tag !=
2767c478bd9Sstevel@tonic-gate 		    V_UNASSIGNED)) {
2777c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_tag = V_UNASSIGNED;
2787c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_start = 0;
2797c478bd9Sstevel@tonic-gate 			old_vtoc->v_part[i].p_size = 0;
2807c478bd9Sstevel@tonic-gate 		}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_UNASSIGNED) {
2837c478bd9Sstevel@tonic-gate 			/* Update count of valid VTOC partitions */
2847c478bd9Sstevel@tonic-gate 			vtoc_part_count++;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			/* Note the highest valid VTOC slice */
2877c478bd9Sstevel@tonic-gate 			highest_assigned_part = i;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	if (vtoc_part_count > vtoc->efi_nparts - 1) {
2917c478bd9Sstevel@tonic-gate 		/* Too many partitions to convert the VTOC label */
2927c478bd9Sstevel@tonic-gate 		err_print("There are %d defined VTOC ", vtoc_part_count);
2937c478bd9Sstevel@tonic-gate 		err_print("partitions and an EFI label\n");
2947c478bd9Sstevel@tonic-gate 		err_print("can only accept %d.\n", vtoc->efi_nparts - 1);
2957c478bd9Sstevel@tonic-gate 		if (check("Continue anyway") != 0) {
2967c478bd9Sstevel@tonic-gate 			/* If no, restore VTOC and return an error */
2977c478bd9Sstevel@tonic-gate 			*old_vtoc = old_vtoc_copy;
2987c478bd9Sstevel@tonic-gate 			efi_free(vtoc);
2997c478bd9Sstevel@tonic-gate 			return (-1);
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	if (highest_assigned_part > vtoc->efi_nparts - 2) {
3047c478bd9Sstevel@tonic-gate 		/*
3057c478bd9Sstevel@tonic-gate 		 * Partition indexes cannot be transferred directly since
3067c478bd9Sstevel@tonic-gate 		 * the highest valid VTOC index is higher than the highest
3077c478bd9Sstevel@tonic-gate 		 * available EFI partition.  Ask the user if it is OK to
3087c478bd9Sstevel@tonic-gate 		 * move the partitions to available slots
3097c478bd9Sstevel@tonic-gate 		 */
3107c478bd9Sstevel@tonic-gate 		err_print("VTOC partition %d is defined ",
3117c478bd9Sstevel@tonic-gate 		    highest_assigned_part);
3127c478bd9Sstevel@tonic-gate 		err_print("and the highest available EFI\n");
3137c478bd9Sstevel@tonic-gate 		err_print("partition is %d.  The partitions\n",
3147c478bd9Sstevel@tonic-gate 		    vtoc->efi_nparts - 2);
3157c478bd9Sstevel@tonic-gate 		err_print("will fit if they are re-numbered\n");
3167c478bd9Sstevel@tonic-gate 		if (check("OK to renumber") != 0) {
3177c478bd9Sstevel@tonic-gate 			/* If no, restore VTOC and return an error */
3187c478bd9Sstevel@tonic-gate 			*old_vtoc = old_vtoc_copy;
3197c478bd9Sstevel@tonic-gate 			efi_free(vtoc);
3207c478bd9Sstevel@tonic-gate 			return (-1);
3217c478bd9Sstevel@tonic-gate 		} else {
3227c478bd9Sstevel@tonic-gate 			compact = 1;
3237c478bd9Sstevel@tonic-gate 		}
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/*
3277c478bd9Sstevel@tonic-gate 	 * Now copy the VTOC partitions, remapping the indices if
3287c478bd9Sstevel@tonic-gate 	 * necessary.
3297c478bd9Sstevel@tonic-gate 	 */
3307c478bd9Sstevel@tonic-gate 	j = 0;
3317c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
3327c478bd9Sstevel@tonic-gate 		if (old_vtoc->v_part[i].p_tag != V_UNASSIGNED) {
3337c478bd9Sstevel@tonic-gate 			/* Copy partition info */
3347c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_tag = old_vtoc->v_part[i].p_tag;
3357c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_flag = old_vtoc->v_part[i].p_flag;
3367c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_start =
3377c478bd9Sstevel@tonic-gate 			    old_vtoc->v_part[i].p_start;
3387c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[j].p_size =
3397c478bd9Sstevel@tonic-gate 			    old_vtoc->v_part[i].p_size;
3407c478bd9Sstevel@tonic-gate 			if (vtoc->efi_parts[j].p_size != 0)
3417c478bd9Sstevel@tonic-gate 				last_par = j;
3427c478bd9Sstevel@tonic-gate 			j++; /* Increment EFI index */
3437c478bd9Sstevel@tonic-gate 		} else {
3447c478bd9Sstevel@tonic-gate 			if (!compact) {
3457c478bd9Sstevel@tonic-gate 				j++; /* Increment EFI index */
3467c478bd9Sstevel@tonic-gate 			}
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	start = vtoc->efi_parts[last_par].p_start;
3517c478bd9Sstevel@tonic-gate 	size = vtoc->efi_parts[last_par].p_size;
3527c478bd9Sstevel@tonic-gate 	if ((start + size) > (vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE)) {
3537c478bd9Sstevel@tonic-gate 		size = (start + size) - (vtoc->efi_last_u_lba -
3547c478bd9Sstevel@tonic-gate 			    EFI_MIN_RESV_SIZE);
3557c478bd9Sstevel@tonic-gate 		vtoc->efi_parts[last_par].p_size -= size;
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
3587c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
3597c478bd9Sstevel@tonic-gate 	    vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE;
3607c478bd9Sstevel@tonic-gate 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	return (0);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate  * This routine constructs and writes a label on the disk.  It writes both
3687c478bd9Sstevel@tonic-gate  * the primary and backup labels.  It assumes that there is a current
3697c478bd9Sstevel@tonic-gate  * partition map already defined.  It also notifies the SunOS kernel of
3707c478bd9Sstevel@tonic-gate  * the label and partition information it has written on the disk.
3717c478bd9Sstevel@tonic-gate  */
3727c478bd9Sstevel@tonic-gate int
3737c478bd9Sstevel@tonic-gate write_label()
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	int	error = 0, head, sec;
3767c478bd9Sstevel@tonic-gate 	struct dk_label label;
3777c478bd9Sstevel@tonic-gate 	struct dk_label new_label;
3787c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
3797c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
3807c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc64;
3817c478bd9Sstevel@tonic-gate 	int		nbackups;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
3847c478bd9Sstevel@tonic-gate 	int i;
3857c478bd9Sstevel@tonic-gate #endif		/* defined(_SUNOS_VTOC_8) */
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/*
3887c478bd9Sstevel@tonic-gate 	 * If EFI label, then write it out to disk
3897c478bd9Sstevel@tonic-gate 	 */
3907c478bd9Sstevel@tonic-gate 	if (cur_label == L_TYPE_EFI) {
3917c478bd9Sstevel@tonic-gate 	    enter_critical();
3927c478bd9Sstevel@tonic-gate 	    vtoc64 = cur_parts->etoc;
3937c478bd9Sstevel@tonic-gate 	    err_check(vtoc64);
3947c478bd9Sstevel@tonic-gate 	    if (efi_write(cur_file, vtoc64) != 0) {
3957c478bd9Sstevel@tonic-gate 		err_print("Warning: error writing EFI.\n");
3967c478bd9Sstevel@tonic-gate 		error = -1;
3977c478bd9Sstevel@tonic-gate 	    }
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	    cur_disk->disk_flags |= DSK_LABEL;
4007c478bd9Sstevel@tonic-gate 	    exit_critical();
4017c478bd9Sstevel@tonic-gate 	    return (error);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	/*
4057c478bd9Sstevel@tonic-gate 	 * Fill in a label structure with the geometry information.
4067c478bd9Sstevel@tonic-gate 	 */
4077c478bd9Sstevel@tonic-gate 	(void) memset((char *)&label, 0, sizeof (struct dk_label));
4087c478bd9Sstevel@tonic-gate 	(void) memset((char *)&new_label, 0, sizeof (struct dk_label));
4097c478bd9Sstevel@tonic-gate 	label.dkl_pcyl = pcyl;
4107c478bd9Sstevel@tonic-gate 	label.dkl_ncyl = ncyl;
4117c478bd9Sstevel@tonic-gate 	label.dkl_acyl = acyl;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
4147c478bd9Sstevel@tonic-gate 	label.dkl_bcyl = bcyl;
4157c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOC_VTOC_16) */
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	label.dkl_nhead = nhead;
4187c478bd9Sstevel@tonic-gate 	label.dkl_nsect = nsect;
4197c478bd9Sstevel@tonic-gate 	label.dkl_apc = apc;
4207c478bd9Sstevel@tonic-gate 	label.dkl_intrlv = 1;
4217c478bd9Sstevel@tonic-gate 	label.dkl_rpm = cur_dtype->dtype_rpm;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
4247c478bd9Sstevel@tonic-gate 	/*
4257c478bd9Sstevel@tonic-gate 	 * Also fill in the current partition information.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
4287c478bd9Sstevel@tonic-gate 		label.dkl_map[i] = cur_parts->pinfo_map[i];
4297c478bd9Sstevel@tonic-gate 	}
4307c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	label.dkl_magic = DKL_MAGIC;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/*
4357c478bd9Sstevel@tonic-gate 	 * Fill in the vtoc information
4367c478bd9Sstevel@tonic-gate 	 */
4377c478bd9Sstevel@tonic-gate 	label.dkl_vtoc = cur_parts->vtoc;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	/*
4407c478bd9Sstevel@tonic-gate 	 * Use the current label
4417c478bd9Sstevel@tonic-gate 	 */
4427c478bd9Sstevel@tonic-gate 	bcopy(cur_disk->v_volume, label.dkl_vtoc.v_volume, LEN_DKL_VVOL);
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 * Put asciilabel in; on x86 it's in the vtoc, not the label.
4467c478bd9Sstevel@tonic-gate 	 */
4477c478bd9Sstevel@tonic-gate 	(void) snprintf(label.dkl_asciilabel, sizeof (label.dkl_asciilabel),
4487c478bd9Sstevel@tonic-gate 	    "%s cyl %d alt %d hd %d sec %d",
4497c478bd9Sstevel@tonic-gate 	    cur_dtype->dtype_asciilabel, ncyl, acyl, nhead, nsect);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
4527c478bd9Sstevel@tonic-gate 	/*
4537c478bd9Sstevel@tonic-gate 	 * Also add in v_sectorsz, as the driver will.  Everyone
4547c478bd9Sstevel@tonic-gate 	 * else is assuming DEV_BSIZE, so we do the same.
4557c478bd9Sstevel@tonic-gate 	 */
4567c478bd9Sstevel@tonic-gate 	label.dkl_vtoc.v_sectorsz = DEV_BSIZE;
4577c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	/*
4607c478bd9Sstevel@tonic-gate 	 * Generate the correct checksum.
4617c478bd9Sstevel@tonic-gate 	 */
4627c478bd9Sstevel@tonic-gate 	(void) checksum(&label, CK_MAKESUM);
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * Convert the label into a vtoc
4657c478bd9Sstevel@tonic-gate 	 */
4667c478bd9Sstevel@tonic-gate 	if (label_to_vtoc(&vtoc, &label) == -1) {
4677c478bd9Sstevel@tonic-gate 		return (-1);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	/*
4707c478bd9Sstevel@tonic-gate 	 * Fill in the geometry info.  This is critical that
4717c478bd9Sstevel@tonic-gate 	 * we do this before writing the vtoc.
4727c478bd9Sstevel@tonic-gate 	 */
4737c478bd9Sstevel@tonic-gate 	bzero((caddr_t)&geom, sizeof (struct dk_geom));
4747c478bd9Sstevel@tonic-gate 	geom.dkg_ncyl = ncyl;
4757c478bd9Sstevel@tonic-gate 	geom.dkg_acyl = acyl;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
4787c478bd9Sstevel@tonic-gate 	geom.dkg_bcyl = bcyl;
4797c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	geom.dkg_nhead = nhead;
4827c478bd9Sstevel@tonic-gate 	geom.dkg_nsect = nsect;
4837c478bd9Sstevel@tonic-gate 	geom.dkg_intrlv = 1;
4847c478bd9Sstevel@tonic-gate 	geom.dkg_apc = apc;
4857c478bd9Sstevel@tonic-gate 	geom.dkg_rpm = cur_dtype->dtype_rpm;
4867c478bd9Sstevel@tonic-gate 	geom.dkg_pcyl = pcyl;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/*
4897c478bd9Sstevel@tonic-gate 	 * Make a quick check to see that the geometry is being
4907c478bd9Sstevel@tonic-gate 	 * written now is not way off from the actual capacity
4917c478bd9Sstevel@tonic-gate 	 * of the disk. This is only an appoximate check and
4927c478bd9Sstevel@tonic-gate 	 * is only for SCSI disks.
4937c478bd9Sstevel@tonic-gate 	 */
4947c478bd9Sstevel@tonic-gate 	if (SCSI && do_geometry_sanity_check() != 0) {
4957c478bd9Sstevel@tonic-gate 		return (-1);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/*
4997c478bd9Sstevel@tonic-gate 	 * Lock out interrupts so we do things in sync.
5007c478bd9Sstevel@tonic-gate 	 */
5017c478bd9Sstevel@tonic-gate 	enter_critical();
5027c478bd9Sstevel@tonic-gate 	/*
5037c478bd9Sstevel@tonic-gate 	 * Do the ioctl to tell the kernel the geometry.
5047c478bd9Sstevel@tonic-gate 	 */
5057c478bd9Sstevel@tonic-gate 	if (ioctl(cur_file, DKIOCSGEOM, &geom) == -1) {
5067c478bd9Sstevel@tonic-gate 		err_print("Warning: error setting drive geometry.\n");
5077c478bd9Sstevel@tonic-gate 		error = -1;
5087c478bd9Sstevel@tonic-gate 	}
5097c478bd9Sstevel@tonic-gate 	/*
5107c478bd9Sstevel@tonic-gate 	 * Write the vtoc.  At the time of this writing, our
5117c478bd9Sstevel@tonic-gate 	 * drivers convert the vtoc back to a label, and
5127c478bd9Sstevel@tonic-gate 	 * then write both the primary and backup labels.
5137c478bd9Sstevel@tonic-gate 	 * This is not a requirement, however, as we
5147c478bd9Sstevel@tonic-gate 	 * always use an ioctl to read the vtoc from the
5157c478bd9Sstevel@tonic-gate 	 * driver, so it can do as it likes.
5167c478bd9Sstevel@tonic-gate 	 */
5177c478bd9Sstevel@tonic-gate 	if (write_vtoc(cur_file, &vtoc) != 0) {
5187c478bd9Sstevel@tonic-gate 		err_print("Warning: error writing VTOC.\n");
5197c478bd9Sstevel@tonic-gate 		error = -1;
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	/*
5237c478bd9Sstevel@tonic-gate 	 * Calculate where the backup labels went.  They are always on
5247c478bd9Sstevel@tonic-gate 	 * the last alternate cylinder, but some older drives put them
5257c478bd9Sstevel@tonic-gate 	 * on head 2 instead of the last head.  They are always on the
5267c478bd9Sstevel@tonic-gate 	 * first 5 odd sectors of the appropriate track.
5277c478bd9Sstevel@tonic-gate 	 */
5287c478bd9Sstevel@tonic-gate 	if (cur_ctype->ctype_flags & CF_BLABEL)
5297c478bd9Sstevel@tonic-gate 		head  = 2;
5307c478bd9Sstevel@tonic-gate 	else
5317c478bd9Sstevel@tonic-gate 		head = nhead - 1;
5327c478bd9Sstevel@tonic-gate 	/*
5337c478bd9Sstevel@tonic-gate 	 * Read and verify the backup labels.
5347c478bd9Sstevel@tonic-gate 	 */
5357c478bd9Sstevel@tonic-gate 	nbackups = 0;
5367c478bd9Sstevel@tonic-gate 	for (sec = 1; ((sec < BAD_LISTCNT * 2 + 1) && (sec < nsect));
5377c478bd9Sstevel@tonic-gate 	    sec += 2) {
5387c478bd9Sstevel@tonic-gate 		if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, (diskaddr_t)
5397c478bd9Sstevel@tonic-gate 			((chs2bn(ncyl + acyl - 1, head, sec)) + solaris_offset),
5407c478bd9Sstevel@tonic-gate 			1, (caddr_t)&new_label, F_NORMAL, NULL)) {
5417c478bd9Sstevel@tonic-gate 			err_print("Warning: error reading backup label.\n");
5427c478bd9Sstevel@tonic-gate 			error = -1;
5437c478bd9Sstevel@tonic-gate 		} else {
5447c478bd9Sstevel@tonic-gate 			if (bcmp((char *)&label, (char *)&new_label,
5457c478bd9Sstevel@tonic-gate 				sizeof (struct dk_label)) == 0) {
5467c478bd9Sstevel@tonic-gate 					nbackups++;
5477c478bd9Sstevel@tonic-gate 			}
5487c478bd9Sstevel@tonic-gate 		}
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 	if (nbackups != BAD_LISTCNT) {
5517c478bd9Sstevel@tonic-gate 		err_print("Warning: %s\n", nbackups == 0 ?
5527c478bd9Sstevel@tonic-gate 			"no backup labels" :
5537c478bd9Sstevel@tonic-gate 			"some backup labels incorrect");
5547c478bd9Sstevel@tonic-gate 	}
5557c478bd9Sstevel@tonic-gate 	/*
5567c478bd9Sstevel@tonic-gate 	 * Mark the current disk as labelled and notify the kernel of what
5577c478bd9Sstevel@tonic-gate 	 * has happened.
5587c478bd9Sstevel@tonic-gate 	 */
5597c478bd9Sstevel@tonic-gate 	cur_disk->disk_flags |= DSK_LABEL;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	exit_critical();
5627c478bd9Sstevel@tonic-gate 	return (error);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate  * Read the label from the disk.
5687c478bd9Sstevel@tonic-gate  * Do this via the read_vtoc() library routine, then convert it to a label.
5697c478bd9Sstevel@tonic-gate  * We also need a DKIOCGGEOM ioctl to get the disk's geometry.
5707c478bd9Sstevel@tonic-gate  */
5717c478bd9Sstevel@tonic-gate int
5727c478bd9Sstevel@tonic-gate read_label(int fd, struct dk_label *label)
5737c478bd9Sstevel@tonic-gate {
5747c478bd9Sstevel@tonic-gate 	struct vtoc	vtoc;
5757c478bd9Sstevel@tonic-gate 	struct dk_geom	geom;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	if (read_vtoc(fd, &vtoc) < 0 || ioctl(fd, DKIOCGGEOM, &geom) == -1) {
5787c478bd9Sstevel@tonic-gate 		return (-1);
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 	return (vtoc_to_label(label, &vtoc, &geom));
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate 
583*3ccda647Slclee int
584*3ccda647Slclee get_disk_info_from_devid(int fd, struct efi_info *label)
585*3ccda647Slclee {
586*3ccda647Slclee 	ddi_devid_t	devid;
587*3ccda647Slclee 	char		*s;
588*3ccda647Slclee 	int		n;
589*3ccda647Slclee 	char		*vid, *pid;
590*3ccda647Slclee 	int		nvid, npid;
591*3ccda647Slclee 	struct dk_minfo	minf;
592*3ccda647Slclee 	struct dk_cinfo	dkinfo;
593*3ccda647Slclee 
594*3ccda647Slclee 
595*3ccda647Slclee 	if (devid_get(fd, &devid)) {
596*3ccda647Slclee 		if (option_msg && diag_msg)
597*3ccda647Slclee 			err_print("devid_get failed\n");
598*3ccda647Slclee 		return (-1);
599*3ccda647Slclee 	}
600*3ccda647Slclee 
601*3ccda647Slclee 	n = devid_sizeof(devid);
602*3ccda647Slclee 	s = (char *)devid;
603*3ccda647Slclee 
604*3ccda647Slclee 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
605*3ccda647Slclee 		if (option_msg && diag_msg)
606*3ccda647Slclee 			err_print("DKIOCINFO failed\n");
607*3ccda647Slclee 		return (-1);
608*3ccda647Slclee 	}
609*3ccda647Slclee 
610*3ccda647Slclee 	if (dkinfo.dki_ctype != DKC_DIRECT)
611*3ccda647Slclee 		return (-1);
612*3ccda647Slclee 
613*3ccda647Slclee 	vid = s+12;
614*3ccda647Slclee 	if (!(pid = strchr(vid, '=')))
615*3ccda647Slclee 		return (-1);
616*3ccda647Slclee 	nvid = pid - vid;
617*3ccda647Slclee 	pid += 1;
618*3ccda647Slclee 	npid = n - nvid - 13;
619*3ccda647Slclee 
620*3ccda647Slclee 	if (nvid > 9)
621*3ccda647Slclee 		nvid = 9;
622*3ccda647Slclee 	if (npid > 17) {
623*3ccda647Slclee 		pid = pid + npid - 17;
624*3ccda647Slclee 		npid = 17;
625*3ccda647Slclee 	}
626*3ccda647Slclee 
627*3ccda647Slclee 	if (ioctl(fd, DKIOCGMEDIAINFO, &minf) == -1) {
628*3ccda647Slclee 		devid_free(devid);
629*3ccda647Slclee 		return (-1);
630*3ccda647Slclee 	}
631*3ccda647Slclee 
632*3ccda647Slclee 	(void) strlcpy(label->vendor, vid, nvid);
633*3ccda647Slclee 	(void) strlcpy(label->product, pid, npid);
634*3ccda647Slclee 	(void) strlcpy(label->revision, "0001", 5);
635*3ccda647Slclee 	label->capacity = minf.dki_capacity * minf.dki_lbsize / 512;
636*3ccda647Slclee 
637*3ccda647Slclee 	devid_free(devid);
638*3ccda647Slclee 	return (0);
639*3ccda647Slclee }
640*3ccda647Slclee 
6417c478bd9Sstevel@tonic-gate /*
6427c478bd9Sstevel@tonic-gate  * Issue uscsi_inquiry and read_capacity commands to
6437c478bd9Sstevel@tonic-gate  * retrieve the disk's Vendor, Product, Revision and
6447c478bd9Sstevel@tonic-gate  * Capacity information.
6457c478bd9Sstevel@tonic-gate  */
6467c478bd9Sstevel@tonic-gate int
6477c478bd9Sstevel@tonic-gate get_disk_info(int fd, struct efi_info *label)
6487c478bd9Sstevel@tonic-gate {
6497c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	inquiry;
6507c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	capacity;
6517c478bd9Sstevel@tonic-gate 
652*3ccda647Slclee 	if (!get_disk_info_from_devid(fd, label))
653*3ccda647Slclee 		return (0);
654*3ccda647Slclee 
6557c478bd9Sstevel@tonic-gate 	if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
6567c478bd9Sstevel@tonic-gate 		err_print("Inquiry failed on %d\n", fd);
6577c478bd9Sstevel@tonic-gate 		return (-1);
6587c478bd9Sstevel@tonic-gate 	}
6597c478bd9Sstevel@tonic-gate 	if (uscsi_read_capacity(fd, &capacity)) {
6607c478bd9Sstevel@tonic-gate 		err_print("Read Capacity failed for %d\n", fd);
6617c478bd9Sstevel@tonic-gate 		return (-1);
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->vendor, inquiry.inq_vid, 9);
6657c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->product, inquiry.inq_pid, 17);
6667c478bd9Sstevel@tonic-gate 	(void) strlcpy(label->revision, inquiry.inq_revision, 5);
6677c478bd9Sstevel@tonic-gate 	label->capacity = capacity.sc_capacity;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	/* Since we are counting from zero, add 1 to capacity */
6707c478bd9Sstevel@tonic-gate 	label->capacity++;
6717c478bd9Sstevel@tonic-gate 	return (0);
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate int
6757c478bd9Sstevel@tonic-gate read_efi_label(int fd, struct efi_info *label)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc64;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	/* This could fail if there is no label already */
6807c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_read(fd, &vtoc64) < 0) {
6817c478bd9Sstevel@tonic-gate 		return (-1);
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 	if (vtoc64_to_label(label, vtoc64) != 0) {
6847c478bd9Sstevel@tonic-gate 		err_print("vtoc64_to_label failed\n");
6857c478bd9Sstevel@tonic-gate 		return (-1);
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 	efi_free(vtoc64);
6887c478bd9Sstevel@tonic-gate 	if (get_disk_info(fd, label) != 0) {
6897c478bd9Sstevel@tonic-gate 		return (-1);
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate 	return (0);
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate /*
6967c478bd9Sstevel@tonic-gate  * We've read a 64-bit label which has no geometry information.  Use
6977c478bd9Sstevel@tonic-gate  * some heuristics to fake up a geometry that would match the disk in
6987c478bd9Sstevel@tonic-gate  * order to make the rest of format(1M) happy.
6997c478bd9Sstevel@tonic-gate  */
7007c478bd9Sstevel@tonic-gate static int
7017c478bd9Sstevel@tonic-gate vtoc64_to_label(struct efi_info *label, struct dk_gpt *vtoc)
7027c478bd9Sstevel@tonic-gate {
7037c478bd9Sstevel@tonic-gate 	int		i, nparts = 0;
7047c478bd9Sstevel@tonic-gate 	struct dk_gpt	*lmap;
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct efi_info));
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	/* XXX do a sanity check here for nparts */
7097c478bd9Sstevel@tonic-gate 	nparts = vtoc->efi_nparts;
7107c478bd9Sstevel@tonic-gate 	lmap = (struct dk_gpt *) calloc(1, (sizeof (struct dk_part) *
7117c478bd9Sstevel@tonic-gate 		    nparts) + sizeof (struct dk_gpt));
7127c478bd9Sstevel@tonic-gate 	if (lmap == NULL) {
7137c478bd9Sstevel@tonic-gate 		err_print("vtoc64_to_label: unable to allocate lmap\n");
7147c478bd9Sstevel@tonic-gate 		fullabort();
7157c478bd9Sstevel@tonic-gate 	}
7167c478bd9Sstevel@tonic-gate 	label->e_parts = lmap;
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	/*
7197c478bd9Sstevel@tonic-gate 	 * Copy necessary portions
7207c478bd9Sstevel@tonic-gate 	 * XXX Maybe we can use memcpy() ??
7217c478bd9Sstevel@tonic-gate 	 */
7227c478bd9Sstevel@tonic-gate 	lmap->efi_version = vtoc->efi_version;
7237c478bd9Sstevel@tonic-gate 	lmap->efi_nparts = vtoc->efi_nparts;
7247c478bd9Sstevel@tonic-gate 	lmap->efi_part_size = vtoc->efi_part_size;
7257c478bd9Sstevel@tonic-gate 	lmap->efi_lbasize = vtoc->efi_lbasize;
7267c478bd9Sstevel@tonic-gate 	lmap->efi_last_lba = vtoc->efi_last_lba;
7277c478bd9Sstevel@tonic-gate 	lmap->efi_first_u_lba = vtoc->efi_first_u_lba;
7287c478bd9Sstevel@tonic-gate 	lmap->efi_last_u_lba = vtoc->efi_last_u_lba;
7297c478bd9Sstevel@tonic-gate 	lmap->efi_flags = vtoc->efi_flags;
7307c478bd9Sstevel@tonic-gate 	(void) memcpy((uchar_t *)&lmap->efi_disk_uguid,
7317c478bd9Sstevel@tonic-gate 		(uchar_t *)&vtoc->efi_disk_uguid, sizeof (struct uuid));
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	for (i = 0; i < nparts; i++) {
7347c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_tag = vtoc->efi_parts[i].p_tag;
7357c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_flag = vtoc->efi_parts[i].p_flag;
7367c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_start = vtoc->efi_parts[i].p_start;
7377c478bd9Sstevel@tonic-gate 		lmap->efi_parts[i].p_size = vtoc->efi_parts[i].p_size;
7387c478bd9Sstevel@tonic-gate 		(void) memcpy((uchar_t *)&lmap->efi_parts[i].p_uguid,
7397c478bd9Sstevel@tonic-gate 		    (uchar_t *)&vtoc->efi_parts[i].p_uguid,
7407c478bd9Sstevel@tonic-gate 		    sizeof (struct uuid));
7417c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
7427c478bd9Sstevel@tonic-gate 			bcopy(vtoc->efi_parts[i].p_name,
7437c478bd9Sstevel@tonic-gate 			    lmap->efi_parts[i].p_name, LEN_DKL_VVOL);
7447c478bd9Sstevel@tonic-gate 		}
7457c478bd9Sstevel@tonic-gate 	}
7467c478bd9Sstevel@tonic-gate 	return (0);
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate /*
7507c478bd9Sstevel@tonic-gate  * Convert vtoc/geom to label.
7517c478bd9Sstevel@tonic-gate  */
7527c478bd9Sstevel@tonic-gate static int
7537c478bd9Sstevel@tonic-gate vtoc_to_label(struct dk_label *label, struct vtoc *vtoc, struct dk_geom *geom)
7547c478bd9Sstevel@tonic-gate {
7557c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
7567c478bd9Sstevel@tonic-gate 	struct dk_map32		*lmap;
7577c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
7587c478bd9Sstevel@tonic-gate 	struct dkl_partition	*lmap;
7597c478bd9Sstevel@tonic-gate #else
7607c478bd9Sstevel@tonic-gate #error No VTOC format defined.
7617c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	struct partition	*vpart;
7647c478bd9Sstevel@tonic-gate 	long			nblks;
7657c478bd9Sstevel@tonic-gate 	int			i;
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	/*
7707c478bd9Sstevel@tonic-gate 	 * Sanity-check the vtoc
7717c478bd9Sstevel@tonic-gate 	 */
7727c478bd9Sstevel@tonic-gate 	if (vtoc->v_sanity != VTOC_SANE || vtoc->v_sectorsz != DEV_BSIZE ||
7737c478bd9Sstevel@tonic-gate 			vtoc->v_nparts != V_NUMPAR) {
7747c478bd9Sstevel@tonic-gate 		return (-1);
7757c478bd9Sstevel@tonic-gate 	}
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	/*
7787c478bd9Sstevel@tonic-gate 	 * Sanity check of geometry
7797c478bd9Sstevel@tonic-gate 	 */
7807c478bd9Sstevel@tonic-gate 	if (geom->dkg_ncyl == 0 || geom->dkg_nhead == 0 ||
7817c478bd9Sstevel@tonic-gate 			geom->dkg_nsect == 0) {
7827c478bd9Sstevel@tonic-gate 		return (-1);
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	/*
7887c478bd9Sstevel@tonic-gate 	 * Copy necessary portions of the geometry information
7897c478bd9Sstevel@tonic-gate 	 */
7907c478bd9Sstevel@tonic-gate 	label->dkl_rpm = geom->dkg_rpm;
7917c478bd9Sstevel@tonic-gate 	label->dkl_pcyl = geom->dkg_pcyl;
7927c478bd9Sstevel@tonic-gate 	label->dkl_apc = geom->dkg_apc;
7937c478bd9Sstevel@tonic-gate 	label->dkl_intrlv = geom->dkg_intrlv;
7947c478bd9Sstevel@tonic-gate 	label->dkl_ncyl = geom->dkg_ncyl;
7957c478bd9Sstevel@tonic-gate 	label->dkl_acyl = geom->dkg_acyl;
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
7987c478bd9Sstevel@tonic-gate 	label->dkl_bcyl = geom->dkg_bcyl;
7997c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	label->dkl_nhead = geom->dkg_nhead;
8027c478bd9Sstevel@tonic-gate 	label->dkl_nsect = geom->dkg_nsect;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
8057c478bd9Sstevel@tonic-gate 	label->dkl_obs1 = geom->dkg_obs1;
8067c478bd9Sstevel@tonic-gate 	label->dkl_obs2 = geom->dkg_obs2;
8077c478bd9Sstevel@tonic-gate 	label->dkl_obs3 = geom->dkg_obs3;
8087c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	label->dkl_write_reinstruct = geom->dkg_write_reinstruct;
8117c478bd9Sstevel@tonic-gate 	label->dkl_read_reinstruct = geom->dkg_read_reinstruct;
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	/*
8147c478bd9Sstevel@tonic-gate 	 * Copy vtoc structure fields into the disk label dk_vtoc
8157c478bd9Sstevel@tonic-gate 	 */
8167c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_sanity = vtoc->v_sanity;
8177c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_nparts = vtoc->v_nparts;
8187c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_version = vtoc->v_version;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	(void) memcpy(label->dkl_vtoc.v_volume, vtoc->v_volume,
8217c478bd9Sstevel@tonic-gate 		LEN_DKL_VVOL);
8227c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++) {
8237c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_tag = vtoc->v_part[i].p_tag;
8247c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_flag = vtoc->v_part[i].p_flag;
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_bootinfo,
8277c478bd9Sstevel@tonic-gate 		(char *)vtoc->v_bootinfo, sizeof (vtoc->v_bootinfo));
8287c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_reserved,
8297c478bd9Sstevel@tonic-gate 		(char *)vtoc->v_reserved, sizeof (vtoc->v_reserved));
8307c478bd9Sstevel@tonic-gate 	(void) memcpy((char *)label->dkl_vtoc.v_timestamp,
8317c478bd9Sstevel@tonic-gate 		(char *)vtoc->timestamp, sizeof (vtoc->timestamp));
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	(void) memcpy(label->dkl_asciilabel, vtoc->v_asciilabel,
8347c478bd9Sstevel@tonic-gate 		LEN_DKL_ASCII);
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	/*
8377c478bd9Sstevel@tonic-gate 	 * Note the conversion from starting sector number
8387c478bd9Sstevel@tonic-gate 	 * to starting cylinder number.
8397c478bd9Sstevel@tonic-gate 	 * Return error if division results in a remainder.
8407c478bd9Sstevel@tonic-gate 	 */
8417c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
8427c478bd9Sstevel@tonic-gate 	lmap = label->dkl_map;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
8457c478bd9Sstevel@tonic-gate 	lmap = label->dkl_vtoc.v_part;
8467c478bd9Sstevel@tonic-gate #else
8477c478bd9Sstevel@tonic-gate #error No VTOC format defined.
8487c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	vpart = vtoc->v_part;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	nblks = (int)label->dkl_nsect * (int)label->dkl_nhead;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++, lmap++, vpart++) {
8557c478bd9Sstevel@tonic-gate 		if ((vpart->p_start % nblks) != 0 ||
8567c478bd9Sstevel@tonic-gate 				(vpart->p_size % nblks) != 0) {
8577c478bd9Sstevel@tonic-gate 			return (-1);
8587c478bd9Sstevel@tonic-gate 		}
8597c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
8607c478bd9Sstevel@tonic-gate 		lmap->dkl_cylno = vpart->p_start / nblks;
8617c478bd9Sstevel@tonic-gate 		lmap->dkl_nblk = vpart->p_size;
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
8647c478bd9Sstevel@tonic-gate 		lmap->p_start = vpart->p_start;
8657c478bd9Sstevel@tonic-gate 		lmap->p_size = vpart->p_size;
8667c478bd9Sstevel@tonic-gate #else
8677c478bd9Sstevel@tonic-gate #error No VTOC format defined.
8687c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
8697c478bd9Sstevel@tonic-gate 	}
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	/*
8727c478bd9Sstevel@tonic-gate 	 * Finally, make a checksum
8737c478bd9Sstevel@tonic-gate 	 */
8747c478bd9Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	return (0);
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate /*
8827c478bd9Sstevel@tonic-gate  * Extract a vtoc structure out of a valid label
8837c478bd9Sstevel@tonic-gate  */
8847c478bd9Sstevel@tonic-gate int
8857c478bd9Sstevel@tonic-gate label_to_vtoc(struct vtoc *vtoc, struct dk_label *label)
8867c478bd9Sstevel@tonic-gate {
8877c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
8887c478bd9Sstevel@tonic-gate 	struct dk_map2		*lpart;
8897c478bd9Sstevel@tonic-gate 	struct dk_map32		*lmap;
8907c478bd9Sstevel@tonic-gate 	long			nblks;
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
8937c478bd9Sstevel@tonic-gate 	struct dkl_partition	*lpart;
8947c478bd9Sstevel@tonic-gate #else
8957c478bd9Sstevel@tonic-gate #error No VTOC format defined.
8967c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	struct partition	*vpart;
8997c478bd9Sstevel@tonic-gate 	int			i;
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	(void) memset((char *)vtoc, 0, sizeof (struct vtoc));
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	switch (label->dkl_vtoc.v_version) {
9047c478bd9Sstevel@tonic-gate 	case 0:
9057c478bd9Sstevel@tonic-gate 		/*
9067c478bd9Sstevel@tonic-gate 		 * No valid vtoc information in the label.
9077c478bd9Sstevel@tonic-gate 		 * Construct default p_flags and p_tags.
9087c478bd9Sstevel@tonic-gate 		 */
9097c478bd9Sstevel@tonic-gate 		vpart = vtoc->v_part;
9107c478bd9Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++, vpart++) {
9117c478bd9Sstevel@tonic-gate 			vpart->p_tag = default_vtoc_map[i].p_tag;
9127c478bd9Sstevel@tonic-gate 			vpart->p_flag = default_vtoc_map[i].p_flag;
9137c478bd9Sstevel@tonic-gate 		}
9147c478bd9Sstevel@tonic-gate 		break;
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	case V_VERSION:
9177c478bd9Sstevel@tonic-gate 		vpart = vtoc->v_part;
9187c478bd9Sstevel@tonic-gate 		lpart = label->dkl_vtoc.v_part;
9197c478bd9Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++, vpart++, lpart++) {
9207c478bd9Sstevel@tonic-gate 			vpart->p_tag = lpart->p_tag;
9217c478bd9Sstevel@tonic-gate 			vpart->p_flag = lpart->p_flag;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
9247c478bd9Sstevel@tonic-gate 			vpart->p_start = lpart->p_start;
9257c478bd9Sstevel@tonic-gate 			vpart->p_size = lpart->p_size;
9267c478bd9Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_16) */
9277c478bd9Sstevel@tonic-gate 		}
9287c478bd9Sstevel@tonic-gate 		(void) memcpy(vtoc->v_volume, label->dkl_vtoc.v_volume,
9297c478bd9Sstevel@tonic-gate 			LEN_DKL_VVOL);
9307c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->v_bootinfo,
9317c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_bootinfo,
9327c478bd9Sstevel@tonic-gate 				sizeof (vtoc->v_bootinfo));
9337c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->v_reserved,
9347c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_reserved,
9357c478bd9Sstevel@tonic-gate 				sizeof (vtoc->v_reserved));
9367c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)vtoc->timestamp,
9377c478bd9Sstevel@tonic-gate 			(char *)label->dkl_vtoc.v_timestamp,
9387c478bd9Sstevel@tonic-gate 				sizeof (vtoc->timestamp));
9397c478bd9Sstevel@tonic-gate 		break;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	default:
9427c478bd9Sstevel@tonic-gate 		return (-1);
9437c478bd9Sstevel@tonic-gate 	}
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	/*
9467c478bd9Sstevel@tonic-gate 	 * XXX - this looks wrong to me....
9477c478bd9Sstevel@tonic-gate 	 * why are these values hardwired, rather than returned from
9487c478bd9Sstevel@tonic-gate 	 * the real disk label?
9497c478bd9Sstevel@tonic-gate 	 */
9507c478bd9Sstevel@tonic-gate 	vtoc->v_sanity = VTOC_SANE;
9517c478bd9Sstevel@tonic-gate 	vtoc->v_version = V_VERSION;
9527c478bd9Sstevel@tonic-gate 	vtoc->v_sectorsz = DEV_BSIZE;
9537c478bd9Sstevel@tonic-gate 	vtoc->v_nparts = V_NUMPAR;
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	(void) memcpy(vtoc->v_asciilabel, label->dkl_asciilabel,
9567c478bd9Sstevel@tonic-gate 		LEN_DKL_ASCII);
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
9597c478bd9Sstevel@tonic-gate 	/*
9607c478bd9Sstevel@tonic-gate 	 * Convert partitioning information.
9617c478bd9Sstevel@tonic-gate 	 * Note the conversion from starting cylinder number
9627c478bd9Sstevel@tonic-gate 	 * to starting sector number.
9637c478bd9Sstevel@tonic-gate 	 */
9647c478bd9Sstevel@tonic-gate 	lmap = label->dkl_map;
9657c478bd9Sstevel@tonic-gate 	vpart = vtoc->v_part;
9667c478bd9Sstevel@tonic-gate 	nblks = label->dkl_nsect * label->dkl_nhead;
9677c478bd9Sstevel@tonic-gate 	for (i = 0; i < V_NUMPAR; i++, vpart++, lmap++) {
9687c478bd9Sstevel@tonic-gate 		vpart->p_start = lmap->dkl_cylno * nblks;
9697c478bd9Sstevel@tonic-gate 		vpart->p_size = lmap->dkl_nblk;
9707c478bd9Sstevel@tonic-gate 	}
9717c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_8) */
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	return (0);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate /*
9777c478bd9Sstevel@tonic-gate  * Input: File descriptor
9787c478bd9Sstevel@tonic-gate  * Output: 1 if disk is >1TB OR has an EFI label, 0 otherwise.
9797c478bd9Sstevel@tonic-gate  */
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate int
9827c478bd9Sstevel@tonic-gate is_efi_type(int fd)
9837c478bd9Sstevel@tonic-gate {
9847c478bd9Sstevel@tonic-gate 	struct vtoc vtoc;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1) {
9877c478bd9Sstevel@tonic-gate 		if (errno == ENOTSUP) {
9887c478bd9Sstevel@tonic-gate 			return (1);
9897c478bd9Sstevel@tonic-gate 		}
9907c478bd9Sstevel@tonic-gate 	}
9917c478bd9Sstevel@tonic-gate 	return (0);
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate /* make sure the user specified something reasonable */
9957c478bd9Sstevel@tonic-gate void
9967c478bd9Sstevel@tonic-gate err_check(struct dk_gpt *vtoc)
9977c478bd9Sstevel@tonic-gate {
9987c478bd9Sstevel@tonic-gate 	int			resv_part = -1;
9997c478bd9Sstevel@tonic-gate 	int			i, j;
10007c478bd9Sstevel@tonic-gate 	diskaddr_t		istart, jstart, isize, jsize, endsect;
10017c478bd9Sstevel@tonic-gate 	int			overlap = 0;
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	/*
10047c478bd9Sstevel@tonic-gate 	 * make sure no partitions overlap
10057c478bd9Sstevel@tonic-gate 	 */
10067c478bd9Sstevel@tonic-gate 	for (i = 0; i < vtoc->efi_nparts; i++) {
10077c478bd9Sstevel@tonic-gate 		/* It can't be unassigned and have an actual size */
10087c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) &&
10097c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_size != 0)) {
10107c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10117c478bd9Sstevel@tonic-gate "partition %d is \"unassigned\" but has a size of %llu\n", i,
10127c478bd9Sstevel@tonic-gate 			vtoc->efi_parts[i].p_size);
10137c478bd9Sstevel@tonic-gate 		}
10147c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) {
10157c478bd9Sstevel@tonic-gate 			continue;
10167c478bd9Sstevel@tonic-gate 		}
10177c478bd9Sstevel@tonic-gate 		if (vtoc->efi_parts[i].p_tag == V_RESERVED) {
10187c478bd9Sstevel@tonic-gate 			if (resv_part != -1) {
10197c478bd9Sstevel@tonic-gate 			    (void) fprintf(stderr,
10207c478bd9Sstevel@tonic-gate "found duplicate reserved partition at %d\n",
10217c478bd9Sstevel@tonic-gate 				i);
10227c478bd9Sstevel@tonic-gate 			}
10237c478bd9Sstevel@tonic-gate 			resv_part = i;
10247c478bd9Sstevel@tonic-gate 			if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE)
10257c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
10267c478bd9Sstevel@tonic-gate "Warning: reserved partition size must be %d sectors\n",
10277c478bd9Sstevel@tonic-gate 				EFI_MIN_RESV_SIZE);
10287c478bd9Sstevel@tonic-gate 		}
10297c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) ||
10307c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) {
10317c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10327c478bd9Sstevel@tonic-gate 			    "Partition %d starts at %llu\n",
10337c478bd9Sstevel@tonic-gate 			    i,
10347c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_start);
10357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10367c478bd9Sstevel@tonic-gate 			    "It must be between %llu and %llu.\n",
10377c478bd9Sstevel@tonic-gate 			    vtoc->efi_first_u_lba,
10387c478bd9Sstevel@tonic-gate 			    vtoc->efi_last_u_lba);
10397c478bd9Sstevel@tonic-gate 		}
10407c478bd9Sstevel@tonic-gate 		if ((vtoc->efi_parts[i].p_start +
10417c478bd9Sstevel@tonic-gate 		    vtoc->efi_parts[i].p_size <
10427c478bd9Sstevel@tonic-gate 		    vtoc->efi_first_u_lba) ||
10437c478bd9Sstevel@tonic-gate 		    (vtoc->efi_parts[i].p_start +
10447c478bd9Sstevel@tonic-gate 		    vtoc->efi_parts[i].p_size >
10457c478bd9Sstevel@tonic-gate 		    vtoc->efi_last_u_lba + 1)) {
10467c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10477c478bd9Sstevel@tonic-gate 			    "Partition %d ends at %llu\n",
10487c478bd9Sstevel@tonic-gate 			    i,
10497c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_start +
10507c478bd9Sstevel@tonic-gate 			    vtoc->efi_parts[i].p_size);
10517c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
10527c478bd9Sstevel@tonic-gate 			    "It must be between %llu and %llu.\n",
10537c478bd9Sstevel@tonic-gate 			    vtoc->efi_first_u_lba,
10547c478bd9Sstevel@tonic-gate 			    vtoc->efi_last_u_lba);
10557c478bd9Sstevel@tonic-gate 		}
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 		for (j = 0; j < vtoc->efi_nparts; j++) {
10587c478bd9Sstevel@tonic-gate 			isize = vtoc->efi_parts[i].p_size;
10597c478bd9Sstevel@tonic-gate 			jsize = vtoc->efi_parts[j].p_size;
10607c478bd9Sstevel@tonic-gate 			istart = vtoc->efi_parts[i].p_start;
10617c478bd9Sstevel@tonic-gate 			jstart = vtoc->efi_parts[j].p_start;
10627c478bd9Sstevel@tonic-gate 			if ((i != j) && (isize != 0) && (jsize != 0)) {
10637c478bd9Sstevel@tonic-gate 				endsect = jstart + jsize -1;
10647c478bd9Sstevel@tonic-gate 				if ((jstart <= istart) &&
10657c478bd9Sstevel@tonic-gate 				    (istart <= endsect)) {
10667c478bd9Sstevel@tonic-gate 					if (!overlap) {
10677c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
10687c478bd9Sstevel@tonic-gate "label error: EFI Labels do not support overlapping partitions\n");
10697c478bd9Sstevel@tonic-gate 					}
10707c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
10717c478bd9Sstevel@tonic-gate "Partition %d overlaps partition %d.\n", i, j);
10727c478bd9Sstevel@tonic-gate 					overlap = 1;
10737c478bd9Sstevel@tonic-gate 				}
10747c478bd9Sstevel@tonic-gate 			}
10757c478bd9Sstevel@tonic-gate 		}
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 	/* make sure there is a reserved partition */
10787c478bd9Sstevel@tonic-gate 	if (resv_part == -1) {
10797c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
10807c478bd9Sstevel@tonic-gate 			"no reserved partition found\n");
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate #ifdef	FOR_DEBUGGING_ONLY
10857c478bd9Sstevel@tonic-gate int
10867c478bd9Sstevel@tonic-gate dump_label(label)
10877c478bd9Sstevel@tonic-gate 	struct dk_label	*label;
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate 	int		i;
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	fmt_print("%s\n", label->dkl_asciilabel);
10927c478bd9Sstevel@tonic-gate 
10937c478bd9Sstevel@tonic-gate 	fmt_print("version:  %d\n", label->dkl_vtoc.v_version);
10947c478bd9Sstevel@tonic-gate 	fmt_print("volume:   ");
10957c478bd9Sstevel@tonic-gate 	for (i = 0; i < LEN_DKL_VVOL; i++) {
10967c478bd9Sstevel@tonic-gate 		if (label->dkl_vtoc.v_volume[i] == 0)
10977c478bd9Sstevel@tonic-gate 			break;
10987c478bd9Sstevel@tonic-gate 		fmt_print("%c", label->dkl_vtoc.v_volume[i]);
10997c478bd9Sstevel@tonic-gate 	}
11007c478bd9Sstevel@tonic-gate 	fmt_print("\n");
11017c478bd9Sstevel@tonic-gate 	fmt_print("v_nparts: %d\n", label->dkl_vtoc.v_nparts);
11027c478bd9Sstevel@tonic-gate 	fmt_print("v_sanity: %lx\n", label->dkl_vtoc.v_sanity);
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
11057c478bd9Sstevel@tonic-gate 	fmt_print("rpm:      %d\n", label->dkl_rpm);
11067c478bd9Sstevel@tonic-gate 	fmt_print("pcyl:     %d\n", label->dkl_pcyl);
11077c478bd9Sstevel@tonic-gate 	fmt_print("apc:      %d\n", label->dkl_apc);
11087c478bd9Sstevel@tonic-gate 	fmt_print("obs1:     %d\n", label->dkl_obs1);
11097c478bd9Sstevel@tonic-gate 	fmt_print("obs2:     %d\n", label->dkl_obs2);
11107c478bd9Sstevel@tonic-gate 	fmt_print("intrlv:   %d\n", label->dkl_intrlv);
11117c478bd9Sstevel@tonic-gate 	fmt_print("ncyl:     %d\n", label->dkl_ncyl);
11127c478bd9Sstevel@tonic-gate 	fmt_print("acyl:     %d\n", label->dkl_acyl);
11137c478bd9Sstevel@tonic-gate 	fmt_print("nhead:    %d\n", label->dkl_nhead);
11147c478bd9Sstevel@tonic-gate 	fmt_print("nsect:    %d\n", label->dkl_nsect);
11157c478bd9Sstevel@tonic-gate 	fmt_print("obs3:     %d\n", label->dkl_obs3);
11167c478bd9Sstevel@tonic-gate 	fmt_print("obs4:     %d\n", label->dkl_obs4);
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
11197c478bd9Sstevel@tonic-gate 	fmt_print("rpm:      %d\n", label->dkl_rpm);
11207c478bd9Sstevel@tonic-gate 	fmt_print("pcyl:     %d\n", label->dkl_pcyl);
11217c478bd9Sstevel@tonic-gate 	fmt_print("apc:      %d\n", label->dkl_apc);
11227c478bd9Sstevel@tonic-gate 	fmt_print("intrlv:   %d\n", label->dkl_intrlv);
11237c478bd9Sstevel@tonic-gate 	fmt_print("ncyl:     %d\n", label->dkl_ncyl);
11247c478bd9Sstevel@tonic-gate 	fmt_print("acyl:     %d\n", label->dkl_acyl);
11257c478bd9Sstevel@tonic-gate 	fmt_print("nhead:    %d\n", label->dkl_nhead);
11267c478bd9Sstevel@tonic-gate 	fmt_print("nsect:    %d\n", label->dkl_nsect);
11277c478bd9Sstevel@tonic-gate 	fmt_print("bcyl:     %d\n", label->dkl_bcyl);
11287c478bd9Sstevel@tonic-gate 	fmt_print("skew:     %d\n", label->dkl_skew);
11297c478bd9Sstevel@tonic-gate #else
11307c478bd9Sstevel@tonic-gate #error No VTOC format defined.
11317c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
11327c478bd9Sstevel@tonic-gate 	fmt_print("magic:    %0x\n", label->dkl_magic);
11337c478bd9Sstevel@tonic-gate 	fmt_print("cksum:    %0x\n", label->dkl_cksum);
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
11387c478bd9Sstevel@tonic-gate 		fmt_print("%c:        cyl=%d, blocks=%d", i+'a',
11397c478bd9Sstevel@tonic-gate 			label->dkl_map[i].dkl_cylno,
11407c478bd9Sstevel@tonic-gate 			label->dkl_map[i].dkl_nblk);
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
11437c478bd9Sstevel@tonic-gate 		fmt_print("%c:        start=%d, blocks=%d", i+'a',
11447c478bd9Sstevel@tonic-gate 		    label->dkl_vtoc.v_part[i].p_start,
11457c478bd9Sstevel@tonic-gate 		    label->dkl_vtoc.v_part[i].p_size);
11467c478bd9Sstevel@tonic-gate #else
11477c478bd9Sstevel@tonic-gate #error No VTOC format defined.
11487c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		fmt_print(",  tag=%d,  flag=%d",
11517c478bd9Sstevel@tonic-gate 			label->dkl_vtoc.v_part[i].p_tag,
11527c478bd9Sstevel@tonic-gate 			label->dkl_vtoc.v_part[i].p_flag);
11537c478bd9Sstevel@tonic-gate 		fmt_print("\n");
11547c478bd9Sstevel@tonic-gate 	}
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	fmt_print("read_reinstruct:  %d\n", label->dkl_read_reinstruct);
11577c478bd9Sstevel@tonic-gate 	fmt_print("write_reinstruct: %d\n", label->dkl_write_reinstruct);
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate 	fmt_print("bootinfo: ");
11607c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; i++) {
11617c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_bootinfo[i]);
11627c478bd9Sstevel@tonic-gate 	}
11637c478bd9Sstevel@tonic-gate 	fmt_print("\n");
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate 	fmt_print("reserved: ");
11667c478bd9Sstevel@tonic-gate 	for (i = 0; i < 10; i++) {
11677c478bd9Sstevel@tonic-gate 		if ((i % 4) == 3)
11687c478bd9Sstevel@tonic-gate 			fmt_print("\n");
11697c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_reserved[i]);
11707c478bd9Sstevel@tonic-gate 	}
11717c478bd9Sstevel@tonic-gate 	fmt_print("\n");
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	fmt_print("timestamp:\n");
11747c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
11757c478bd9Sstevel@tonic-gate 		if ((i % 4) == 3)
11767c478bd9Sstevel@tonic-gate 			fmt_print("\n");
11777c478bd9Sstevel@tonic-gate 		fmt_print("0x%x ", label->dkl_vtoc.v_timestamp[i]);
11787c478bd9Sstevel@tonic-gate 	}
11797c478bd9Sstevel@tonic-gate 	fmt_print("\n");
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	fmt_print("pad:\n");
11827c478bd9Sstevel@tonic-gate 	dump("", label->dkl_pad, LEN_DKL_PAD, HEX_ONLY);
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	fmt_print("\n\n");
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate #endif	/* FOR_DEBUGGING_ONLY */
1187