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