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