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 #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <errno.h> 32*7c478bd9Sstevel@tonic-gate #include <strings.h> 33*7c478bd9Sstevel@tonic-gate #include <unistd.h> 34*7c478bd9Sstevel@tonic-gate #include <uuid/uuid.h> 35*7c478bd9Sstevel@tonic-gate #include <libintl.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/mhd.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/byteorder.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate static struct uuid_to_ptag { 47*7c478bd9Sstevel@tonic-gate struct uuid uuid; 48*7c478bd9Sstevel@tonic-gate } conversion_array[] = { 49*7c478bd9Sstevel@tonic-gate { EFI_UNUSED }, 50*7c478bd9Sstevel@tonic-gate { EFI_BOOT }, 51*7c478bd9Sstevel@tonic-gate { EFI_ROOT }, 52*7c478bd9Sstevel@tonic-gate { EFI_SWAP }, 53*7c478bd9Sstevel@tonic-gate { EFI_USR }, 54*7c478bd9Sstevel@tonic-gate { EFI_BACKUP }, 55*7c478bd9Sstevel@tonic-gate { 0 }, /* STAND is never used */ 56*7c478bd9Sstevel@tonic-gate { EFI_VAR }, 57*7c478bd9Sstevel@tonic-gate { EFI_HOME }, 58*7c478bd9Sstevel@tonic-gate { EFI_ALTSCTR }, 59*7c478bd9Sstevel@tonic-gate { 0 }, /* CACHE (cachefs) is never used */ 60*7c478bd9Sstevel@tonic-gate { EFI_RESERVED }, 61*7c478bd9Sstevel@tonic-gate { EFI_SYSTEM }, 62*7c478bd9Sstevel@tonic-gate { EFI_LEGACY_MBR }, 63*7c478bd9Sstevel@tonic-gate { EFI_RESV3 }, 64*7c478bd9Sstevel@tonic-gate { EFI_RESV4 }, 65*7c478bd9Sstevel@tonic-gate { EFI_MSFT_RESV }, 66*7c478bd9Sstevel@tonic-gate { EFI_DELL_BASIC }, 67*7c478bd9Sstevel@tonic-gate { EFI_DELL_RAID }, 68*7c478bd9Sstevel@tonic-gate { EFI_DELL_SWAP }, 69*7c478bd9Sstevel@tonic-gate { EFI_DELL_LVM }, 70*7c478bd9Sstevel@tonic-gate { EFI_DELL_RESV } 71*7c478bd9Sstevel@tonic-gate }; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Default vtoc information for non-SVr4 partitions 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate struct dk_map2 default_vtoc_map[NDKMAP] = { 77*7c478bd9Sstevel@tonic-gate { V_ROOT, 0 }, /* a - 0 */ 78*7c478bd9Sstevel@tonic-gate { V_SWAP, V_UNMNT }, /* b - 1 */ 79*7c478bd9Sstevel@tonic-gate { V_BACKUP, V_UNMNT }, /* c - 2 */ 80*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* d - 3 */ 81*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* e - 4 */ 82*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* f - 5 */ 83*7c478bd9Sstevel@tonic-gate { V_USR, 0 }, /* g - 6 */ 84*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* h - 7 */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16) 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate #if defined(i386) || defined(__amd64) 89*7c478bd9Sstevel@tonic-gate { V_BOOT, V_UNMNT }, /* i - 8 */ 90*7c478bd9Sstevel@tonic-gate { V_ALTSCTR, 0 }, /* j - 9 */ 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate #else 93*7c478bd9Sstevel@tonic-gate #error No VTOC format defined. 94*7c478bd9Sstevel@tonic-gate #endif /* defined(i386) */ 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* k - 10 */ 97*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* l - 11 */ 98*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* m - 12 */ 99*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* n - 13 */ 100*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* o - 14 */ 101*7c478bd9Sstevel@tonic-gate { V_UNASSIGNED, 0 }, /* p - 15 */ 102*7c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */ 103*7c478bd9Sstevel@tonic-gate }; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * This is the size of the reserved partition. 107*7c478bd9Sstevel@tonic-gate * Valid in case of EFI labels. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate #define EFI_MIN_RESV_SIZE (16 * 1024) 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 112*7c478bd9Sstevel@tonic-gate int efi_debug = 1; 113*7c478bd9Sstevel@tonic-gate #else 114*7c478bd9Sstevel@tonic-gate int efi_debug = 0; 115*7c478bd9Sstevel@tonic-gate #endif 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate extern unsigned int efi_crc32(const unsigned char *, unsigned int); 118*7c478bd9Sstevel@tonic-gate static int efi_read(int, struct dk_gpt *); 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate static int 121*7c478bd9Sstevel@tonic-gate read_disk_info(int fd, diskaddr_t *capacity, uint_t *lbsize) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate struct dk_minfo disk_info; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate if ((ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info)) == -1) 126*7c478bd9Sstevel@tonic-gate return (errno); 127*7c478bd9Sstevel@tonic-gate *capacity = disk_info.dki_capacity; 128*7c478bd9Sstevel@tonic-gate *lbsize = disk_info.dki_lbsize; 129*7c478bd9Sstevel@tonic-gate return (0); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * the number of blocks the EFI label takes up (round up to nearest 134*7c478bd9Sstevel@tonic-gate * block) 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate #define NBLOCKS(p, l) (1 + ((((p) * (int)sizeof (efi_gpe_t)) + \ 137*7c478bd9Sstevel@tonic-gate ((l) - 1)) / (l))) 138*7c478bd9Sstevel@tonic-gate /* number of partitions -- limited by what we can malloc */ 139*7c478bd9Sstevel@tonic-gate #define MAX_PARTS ((4294967295UL - sizeof (struct dk_gpt)) / \ 140*7c478bd9Sstevel@tonic-gate sizeof (struct dk_part)) 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate int 143*7c478bd9Sstevel@tonic-gate efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc) 144*7c478bd9Sstevel@tonic-gate { 145*7c478bd9Sstevel@tonic-gate diskaddr_t capacity; 146*7c478bd9Sstevel@tonic-gate uint_t lbsize; 147*7c478bd9Sstevel@tonic-gate uint_t nblocks; 148*7c478bd9Sstevel@tonic-gate size_t length; 149*7c478bd9Sstevel@tonic-gate struct dk_gpt *vptr; 150*7c478bd9Sstevel@tonic-gate struct uuid uuid; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate if (read_disk_info(fd, &capacity, &lbsize) != 0) { 153*7c478bd9Sstevel@tonic-gate if (efi_debug) 154*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 155*7c478bd9Sstevel@tonic-gate "couldn't read disk information\n"); 156*7c478bd9Sstevel@tonic-gate return (-1); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate nblocks = NBLOCKS(nparts, lbsize); 160*7c478bd9Sstevel@tonic-gate if ((nblocks * lbsize) < EFI_MIN_ARRAY_SIZE + lbsize) { 161*7c478bd9Sstevel@tonic-gate /* 16K plus one block for the GPT */ 162*7c478bd9Sstevel@tonic-gate nblocks = EFI_MIN_ARRAY_SIZE / lbsize + 1; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate if (nparts > MAX_PARTS) { 166*7c478bd9Sstevel@tonic-gate if (efi_debug) { 167*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 168*7c478bd9Sstevel@tonic-gate "the maximum number of partitions supported is %lu\n", 169*7c478bd9Sstevel@tonic-gate MAX_PARTS); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate return (-1); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate length = sizeof (struct dk_gpt) + 175*7c478bd9Sstevel@tonic-gate sizeof (struct dk_part) * (nparts - 1); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if ((*vtoc = calloc(length, 1)) == NULL) 178*7c478bd9Sstevel@tonic-gate return (-1); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate vptr = *vtoc; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate vptr->efi_version = EFI_VERSION_CURRENT; 183*7c478bd9Sstevel@tonic-gate vptr->efi_lbasize = lbsize; 184*7c478bd9Sstevel@tonic-gate vptr->efi_nparts = nparts; 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * add one block here for the PMBR; on disks with a 512 byte 187*7c478bd9Sstevel@tonic-gate * block size and 128 or fewer partitions, efi_first_u_lba 188*7c478bd9Sstevel@tonic-gate * should work out to "34" 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate vptr->efi_first_u_lba = nblocks + 1; 191*7c478bd9Sstevel@tonic-gate vptr->efi_last_lba = capacity - 1; 192*7c478bd9Sstevel@tonic-gate vptr->efi_last_u_lba = vptr->efi_last_lba - nblocks; 193*7c478bd9Sstevel@tonic-gate (void) uuid_generate((uchar_t *)&uuid); 194*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT(vptr->efi_disk_uguid, uuid); 195*7c478bd9Sstevel@tonic-gate return (0); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * Read EFI - return partition number upon success. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate int 202*7c478bd9Sstevel@tonic-gate efi_alloc_and_read(int fd, struct dk_gpt **vtoc) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate int rval; 205*7c478bd9Sstevel@tonic-gate uint32_t nparts; 206*7c478bd9Sstevel@tonic-gate int length; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* figure out the number of entries that would fit into 16K */ 209*7c478bd9Sstevel@tonic-gate nparts = EFI_MIN_ARRAY_SIZE / sizeof (efi_gpe_t); 210*7c478bd9Sstevel@tonic-gate length = (int) sizeof (struct dk_gpt) + 211*7c478bd9Sstevel@tonic-gate (int) sizeof (struct dk_part) * (nparts - 1); 212*7c478bd9Sstevel@tonic-gate if ((*vtoc = calloc(length, 1)) == NULL) 213*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_nparts = nparts; 216*7c478bd9Sstevel@tonic-gate rval = efi_read(fd, *vtoc); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if ((rval == VT_EINVAL) && (*vtoc)->efi_nparts > nparts) { 219*7c478bd9Sstevel@tonic-gate void *tmp; 220*7c478bd9Sstevel@tonic-gate length = (int) sizeof (struct dk_gpt) + 221*7c478bd9Sstevel@tonic-gate (int) sizeof (struct dk_part) * 222*7c478bd9Sstevel@tonic-gate ((*vtoc)->efi_nparts - 1); 223*7c478bd9Sstevel@tonic-gate nparts = (*vtoc)->efi_nparts; 224*7c478bd9Sstevel@tonic-gate if ((tmp = realloc(*vtoc, length)) == NULL) { 225*7c478bd9Sstevel@tonic-gate free (*vtoc); 226*7c478bd9Sstevel@tonic-gate *vtoc = NULL; 227*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 228*7c478bd9Sstevel@tonic-gate } else { 229*7c478bd9Sstevel@tonic-gate *vtoc = tmp; 230*7c478bd9Sstevel@tonic-gate rval = efi_read(fd, *vtoc); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate if (rval < 0) { 235*7c478bd9Sstevel@tonic-gate if (efi_debug) { 236*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 237*7c478bd9Sstevel@tonic-gate "read of EFI table failed, rval=%d\n", rval); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate free (*vtoc); 240*7c478bd9Sstevel@tonic-gate *vtoc = NULL; 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate return (rval); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate static int 247*7c478bd9Sstevel@tonic-gate efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc) 248*7c478bd9Sstevel@tonic-gate { 249*7c478bd9Sstevel@tonic-gate void *data = dk_ioc->dki_data; 250*7c478bd9Sstevel@tonic-gate int error; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data; 253*7c478bd9Sstevel@tonic-gate error = ioctl(fd, cmd, (void *)dk_ioc); 254*7c478bd9Sstevel@tonic-gate dk_ioc->dki_data = data; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate return (error); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate static int 260*7c478bd9Sstevel@tonic-gate check_label(int fd, dk_efi_t *dk_ioc) 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate efi_gpt_t *efi; 263*7c478bd9Sstevel@tonic-gate uint_t crc; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCGETEFI, dk_ioc) == -1) { 266*7c478bd9Sstevel@tonic-gate switch (errno) { 267*7c478bd9Sstevel@tonic-gate case EIO: 268*7c478bd9Sstevel@tonic-gate return (VT_EIO); 269*7c478bd9Sstevel@tonic-gate default: 270*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate efi = dk_ioc->dki_data; 274*7c478bd9Sstevel@tonic-gate if (efi->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) { 275*7c478bd9Sstevel@tonic-gate if (efi_debug) 276*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 277*7c478bd9Sstevel@tonic-gate "Bad EFI signature: 0x%llx != 0x%llx\n", 278*7c478bd9Sstevel@tonic-gate (long long)efi->efi_gpt_Signature, 279*7c478bd9Sstevel@tonic-gate (long long)LE_64(EFI_SIGNATURE)); 280*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * check CRC of the header; the size of the header should 285*7c478bd9Sstevel@tonic-gate * never be larger than one block 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate crc = efi->efi_gpt_HeaderCRC32; 288*7c478bd9Sstevel@tonic-gate efi->efi_gpt_HeaderCRC32 = 0; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate if (((len_t)LE_32(efi->efi_gpt_HeaderSize) > dk_ioc->dki_length) || 291*7c478bd9Sstevel@tonic-gate crc != LE_32(efi_crc32((unsigned char *)efi, 292*7c478bd9Sstevel@tonic-gate LE_32(efi->efi_gpt_HeaderSize)))) { 293*7c478bd9Sstevel@tonic-gate if (efi_debug) 294*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 295*7c478bd9Sstevel@tonic-gate "Bad EFI CRC: 0x%x != 0x%x\n", 296*7c478bd9Sstevel@tonic-gate crc, 297*7c478bd9Sstevel@tonic-gate LE_32(efi_crc32((unsigned char *)efi, 298*7c478bd9Sstevel@tonic-gate sizeof (struct efi_gpt)))); 299*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate return (0); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate static int 306*7c478bd9Sstevel@tonic-gate efi_read(int fd, struct dk_gpt *vtoc) 307*7c478bd9Sstevel@tonic-gate { 308*7c478bd9Sstevel@tonic-gate int i, j; 309*7c478bd9Sstevel@tonic-gate int label_len; 310*7c478bd9Sstevel@tonic-gate int rval = 0; 311*7c478bd9Sstevel@tonic-gate int md_flag = 0; 312*7c478bd9Sstevel@tonic-gate struct dk_minfo disk_info; 313*7c478bd9Sstevel@tonic-gate dk_efi_t dk_ioc; 314*7c478bd9Sstevel@tonic-gate efi_gpt_t *efi; 315*7c478bd9Sstevel@tonic-gate efi_gpe_t *efi_parts; 316*7c478bd9Sstevel@tonic-gate struct dk_cinfo dki_info; 317*7c478bd9Sstevel@tonic-gate uint32_t user_length; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* 320*7c478bd9Sstevel@tonic-gate * get the partition number for this file descriptor. 321*7c478bd9Sstevel@tonic-gate */ 322*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 323*7c478bd9Sstevel@tonic-gate if (efi_debug) 324*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno); 325*7c478bd9Sstevel@tonic-gate switch (errno) { 326*7c478bd9Sstevel@tonic-gate case EIO: 327*7c478bd9Sstevel@tonic-gate return (VT_EIO); 328*7c478bd9Sstevel@tonic-gate case EINVAL: 329*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 330*7c478bd9Sstevel@tonic-gate default: 331*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) && 335*7c478bd9Sstevel@tonic-gate (strncmp(dki_info.dki_dname, "md", 3) == 0)) { 336*7c478bd9Sstevel@tonic-gate md_flag++; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate /* get the LBA size */ 339*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) { 340*7c478bd9Sstevel@tonic-gate if (efi_debug) { 341*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 342*7c478bd9Sstevel@tonic-gate "assuming LBA 512 bytes %d\n", 343*7c478bd9Sstevel@tonic-gate errno); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate disk_info.dki_lbsize = DEV_BSIZE; 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate if (disk_info.dki_lbsize == 0) { 348*7c478bd9Sstevel@tonic-gate if (efi_debug) { 349*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 350*7c478bd9Sstevel@tonic-gate "efi_read: assuming LBA 512 bytes\n"); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate disk_info.dki_lbsize = DEV_BSIZE; 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * Read the EFI GPT to figure out how many partitions we need 356*7c478bd9Sstevel@tonic-gate * to deal with. 357*7c478bd9Sstevel@tonic-gate */ 358*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = 1; 359*7c478bd9Sstevel@tonic-gate if (NBLOCKS(vtoc->efi_nparts, disk_info.dki_lbsize) < 34) { 360*7c478bd9Sstevel@tonic-gate label_len = EFI_MIN_ARRAY_SIZE + disk_info.dki_lbsize; 361*7c478bd9Sstevel@tonic-gate } else { 362*7c478bd9Sstevel@tonic-gate label_len = vtoc->efi_nparts * (int) sizeof (efi_gpe_t) + 363*7c478bd9Sstevel@tonic-gate disk_info.dki_lbsize; 364*7c478bd9Sstevel@tonic-gate if (label_len % disk_info.dki_lbsize) { 365*7c478bd9Sstevel@tonic-gate /* pad to physical sector size */ 366*7c478bd9Sstevel@tonic-gate label_len += disk_info.dki_lbsize; 367*7c478bd9Sstevel@tonic-gate label_len &= ~(disk_info.dki_lbsize - 1); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate if ((dk_ioc.dki_data = calloc(label_len, 1)) == NULL) 372*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = label_len; 375*7c478bd9Sstevel@tonic-gate user_length = vtoc->efi_nparts; 376*7c478bd9Sstevel@tonic-gate efi = dk_ioc.dki_data; 377*7c478bd9Sstevel@tonic-gate if (md_flag) { 378*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) == -1) { 379*7c478bd9Sstevel@tonic-gate switch (errno) { 380*7c478bd9Sstevel@tonic-gate case EIO: 381*7c478bd9Sstevel@tonic-gate return (VT_EIO); 382*7c478bd9Sstevel@tonic-gate default: 383*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate } else if ((rval = check_label(fd, &dk_ioc)) == VT_EINVAL) { 387*7c478bd9Sstevel@tonic-gate /* no valid label here; try the alternate */ 388*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = disk_info.dki_capacity - 1; 389*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = disk_info.dki_lbsize; 390*7c478bd9Sstevel@tonic-gate if (check_label(fd, &dk_ioc) == 0) { 391*7c478bd9Sstevel@tonic-gate if (efi_debug) { 392*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 393*7c478bd9Sstevel@tonic-gate "efi_read: primary label corrupt; " 394*7c478bd9Sstevel@tonic-gate "using backup\n"); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = LE_64(efi->efi_gpt_PartitionEntryLBA); 397*7c478bd9Sstevel@tonic-gate vtoc->efi_flags |= EFI_GPT_PRIMARY_CORRUPT; 398*7c478bd9Sstevel@tonic-gate vtoc->efi_nparts = 399*7c478bd9Sstevel@tonic-gate LE_32(efi->efi_gpt_NumberOfPartitionEntries); 400*7c478bd9Sstevel@tonic-gate /* 401*7c478bd9Sstevel@tonic-gate * partitions are between last usable LBA and 402*7c478bd9Sstevel@tonic-gate * backup partition header 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate dk_ioc.dki_data++; 405*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = disk_info.dki_capacity - 406*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba - 1; 407*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length *= disk_info.dki_lbsize; 408*7c478bd9Sstevel@tonic-gate if (dk_ioc.dki_length > (len_t)label_len) { 409*7c478bd9Sstevel@tonic-gate rval = VT_EINVAL; 410*7c478bd9Sstevel@tonic-gate } else { 411*7c478bd9Sstevel@tonic-gate rval = efi_ioctl(fd, DKIOCGETEFI, &dk_ioc); 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate if (rval < 0) { 416*7c478bd9Sstevel@tonic-gate free(efi); 417*7c478bd9Sstevel@tonic-gate return (rval); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* partitions start in the next block */ 421*7c478bd9Sstevel@tonic-gate /* LINTED -- always longlong aligned */ 422*7c478bd9Sstevel@tonic-gate efi_parts = (efi_gpe_t *)(((char *)efi) + disk_info.dki_lbsize); 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * Assemble this into a "dk_gpt" struct for easier 426*7c478bd9Sstevel@tonic-gate * digestibility by applications. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate vtoc->efi_version = LE_32(efi->efi_gpt_Revision); 429*7c478bd9Sstevel@tonic-gate vtoc->efi_nparts = LE_32(efi->efi_gpt_NumberOfPartitionEntries); 430*7c478bd9Sstevel@tonic-gate vtoc->efi_part_size = LE_32(efi->efi_gpt_SizeOfPartitionEntry); 431*7c478bd9Sstevel@tonic-gate vtoc->efi_lbasize = disk_info.dki_lbsize; 432*7c478bd9Sstevel@tonic-gate vtoc->efi_last_lba = disk_info.dki_capacity - 1; 433*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba = LE_64(efi->efi_gpt_FirstUsableLBA); 434*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba = LE_64(efi->efi_gpt_LastUsableLBA); 435*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT(vtoc->efi_disk_uguid, efi->efi_gpt_DiskGUID); 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * If the array the user passed in is too small, set the length 439*7c478bd9Sstevel@tonic-gate * to what it needs to be and return 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate if (user_length < vtoc->efi_nparts) { 442*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate for (i = 0; i < vtoc->efi_nparts; i++) { 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT(vtoc->efi_parts[i].p_guid, 448*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_PartitionTypeGUID); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate for (j = 0; 451*7c478bd9Sstevel@tonic-gate j < sizeof (conversion_array) / sizeof (struct uuid_to_ptag); 452*7c478bd9Sstevel@tonic-gate j++) { 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate if (bcmp(&vtoc->efi_parts[i].p_guid, 455*7c478bd9Sstevel@tonic-gate &conversion_array[j].uuid, 456*7c478bd9Sstevel@tonic-gate sizeof (struct uuid)) == 0) { 457*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_tag = j; 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) 462*7c478bd9Sstevel@tonic-gate continue; 463*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_flag = 464*7c478bd9Sstevel@tonic-gate LE_16(efi_parts[i].efi_gpe_Attributes.PartitionAttrs); 465*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start = 466*7c478bd9Sstevel@tonic-gate LE_64(efi_parts[i].efi_gpe_StartingLBA); 467*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size = 468*7c478bd9Sstevel@tonic-gate LE_64(efi_parts[i].efi_gpe_EndingLBA) - 469*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start + 1; 470*7c478bd9Sstevel@tonic-gate for (j = 0; j < EFI_PART_NAME_LEN; j++) { 471*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_name[j] = 472*7c478bd9Sstevel@tonic-gate (uchar_t)LE_16(efi_parts[i].efi_gpe_PartitionName[j]); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT(vtoc->efi_parts[i].p_uguid, 476*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_UniquePartitionGUID); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate free(efi); 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate return (dki_info.dki_partition); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate /* writes a "protective" MBR */ 484*7c478bd9Sstevel@tonic-gate static int 485*7c478bd9Sstevel@tonic-gate write_pmbr(int fd, struct dk_gpt *vtoc) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate dk_efi_t dk_ioc; 488*7c478bd9Sstevel@tonic-gate struct mboot mb; 489*7c478bd9Sstevel@tonic-gate uchar_t *cp; 490*7c478bd9Sstevel@tonic-gate diskaddr_t size_in_lba; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate mb.signature = LE_16(MBB_MAGIC); 493*7c478bd9Sstevel@tonic-gate bzero(&mb.parts, sizeof (mb.parts)); 494*7c478bd9Sstevel@tonic-gate cp = (uchar_t *)&mb.parts[0]; 495*7c478bd9Sstevel@tonic-gate /* bootable or not */ 496*7c478bd9Sstevel@tonic-gate *cp++ = 0; 497*7c478bd9Sstevel@tonic-gate /* beginning CHS; 0xffffff if not representable */ 498*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 499*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 500*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 501*7c478bd9Sstevel@tonic-gate /* OS type */ 502*7c478bd9Sstevel@tonic-gate *cp++ = EFI_PMBR; 503*7c478bd9Sstevel@tonic-gate /* ending CHS; 0xffffff if not representable */ 504*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 505*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 506*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 507*7c478bd9Sstevel@tonic-gate /* starting LBA: 1 (little endian format) by EFI definition */ 508*7c478bd9Sstevel@tonic-gate *cp++ = 0x01; 509*7c478bd9Sstevel@tonic-gate *cp++ = 0x00; 510*7c478bd9Sstevel@tonic-gate *cp++ = 0x00; 511*7c478bd9Sstevel@tonic-gate *cp++ = 0x00; 512*7c478bd9Sstevel@tonic-gate /* ending LBA: last block on the disk (little endian format) */ 513*7c478bd9Sstevel@tonic-gate size_in_lba = vtoc->efi_last_lba; 514*7c478bd9Sstevel@tonic-gate if (size_in_lba < 0xffffffff) { 515*7c478bd9Sstevel@tonic-gate *cp++ = (size_in_lba & 0x000000ff); 516*7c478bd9Sstevel@tonic-gate *cp++ = (size_in_lba & 0x0000ff00) >> 8; 517*7c478bd9Sstevel@tonic-gate *cp++ = (size_in_lba & 0x00ff0000) >> 16; 518*7c478bd9Sstevel@tonic-gate *cp++ = (size_in_lba & 0xff000000) >> 24; 519*7c478bd9Sstevel@tonic-gate } else { 520*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 521*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 522*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 523*7c478bd9Sstevel@tonic-gate *cp++ = 0xff; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate /* LINTED -- always longlong aligned */ 526*7c478bd9Sstevel@tonic-gate dk_ioc.dki_data = (efi_gpt_t *)&mb; 527*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = 0; 528*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = sizeof (mb); 529*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 530*7c478bd9Sstevel@tonic-gate switch (errno) { 531*7c478bd9Sstevel@tonic-gate case EIO: 532*7c478bd9Sstevel@tonic-gate return (VT_EIO); 533*7c478bd9Sstevel@tonic-gate case EINVAL: 534*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 535*7c478bd9Sstevel@tonic-gate default: 536*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate } 539*7c478bd9Sstevel@tonic-gate return (0); 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate /* make sure the user specified something reasonable */ 543*7c478bd9Sstevel@tonic-gate static int 544*7c478bd9Sstevel@tonic-gate check_input(struct dk_gpt *vtoc) 545*7c478bd9Sstevel@tonic-gate { 546*7c478bd9Sstevel@tonic-gate int resv_part = -1; 547*7c478bd9Sstevel@tonic-gate int i, j; 548*7c478bd9Sstevel@tonic-gate diskaddr_t istart, jstart, isize, jsize, endsect; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* 551*7c478bd9Sstevel@tonic-gate * Sanity-check the input (make sure no partitions overlap) 552*7c478bd9Sstevel@tonic-gate */ 553*7c478bd9Sstevel@tonic-gate for (i = 0; i < vtoc->efi_nparts; i++) { 554*7c478bd9Sstevel@tonic-gate /* It can't be unassigned and have an actual size */ 555*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) && 556*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_size != 0)) { 557*7c478bd9Sstevel@tonic-gate if (efi_debug) { 558*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 559*7c478bd9Sstevel@tonic-gate "partition %d is \"unassigned\" but has a size of %llu", 560*7c478bd9Sstevel@tonic-gate i, 561*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) { 566*7c478bd9Sstevel@tonic-gate continue; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 569*7c478bd9Sstevel@tonic-gate if (resv_part != -1) { 570*7c478bd9Sstevel@tonic-gate if (efi_debug) { 571*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 572*7c478bd9Sstevel@tonic-gate "found duplicate reserved partition at %d\n", 573*7c478bd9Sstevel@tonic-gate i); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate resv_part = i; 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) || 580*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) { 581*7c478bd9Sstevel@tonic-gate if (efi_debug) { 582*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 583*7c478bd9Sstevel@tonic-gate "Partition %d starts at %llu. ", 584*7c478bd9Sstevel@tonic-gate i, 585*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start); 586*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 587*7c478bd9Sstevel@tonic-gate "It must be between %llu and %llu.\n", 588*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba, 589*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_start + 594*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size < 595*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba) || 596*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_start + 597*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size > 598*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba + 1)) { 599*7c478bd9Sstevel@tonic-gate if (efi_debug) { 600*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 601*7c478bd9Sstevel@tonic-gate "Partition %d ends at %llu. ", 602*7c478bd9Sstevel@tonic-gate i, 603*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start + 604*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size); 605*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 606*7c478bd9Sstevel@tonic-gate "It must be between %llu and %llu.\n", 607*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba, 608*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate for (j = 0; j < vtoc->efi_nparts; j++) { 614*7c478bd9Sstevel@tonic-gate isize = vtoc->efi_parts[i].p_size; 615*7c478bd9Sstevel@tonic-gate jsize = vtoc->efi_parts[j].p_size; 616*7c478bd9Sstevel@tonic-gate istart = vtoc->efi_parts[i].p_start; 617*7c478bd9Sstevel@tonic-gate jstart = vtoc->efi_parts[j].p_start; 618*7c478bd9Sstevel@tonic-gate if ((i != j) && (isize != 0) && (jsize != 0)) { 619*7c478bd9Sstevel@tonic-gate endsect = jstart + jsize -1; 620*7c478bd9Sstevel@tonic-gate if ((jstart <= istart) && 621*7c478bd9Sstevel@tonic-gate (istart <= endsect)) { 622*7c478bd9Sstevel@tonic-gate if (efi_debug) { 623*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 624*7c478bd9Sstevel@tonic-gate "Partition %d overlaps partition %d.", 625*7c478bd9Sstevel@tonic-gate i, j); 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate /* just a warning for now */ 633*7c478bd9Sstevel@tonic-gate if ((resv_part == -1) && efi_debug) { 634*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 635*7c478bd9Sstevel@tonic-gate "no reserved partition found\n"); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate return (0); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * write EFI label and backup label 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate int 644*7c478bd9Sstevel@tonic-gate efi_write(int fd, struct dk_gpt *vtoc) 645*7c478bd9Sstevel@tonic-gate { 646*7c478bd9Sstevel@tonic-gate dk_efi_t dk_ioc; 647*7c478bd9Sstevel@tonic-gate efi_gpt_t *efi; 648*7c478bd9Sstevel@tonic-gate efi_gpe_t *efi_parts; 649*7c478bd9Sstevel@tonic-gate int i, j; 650*7c478bd9Sstevel@tonic-gate struct dk_cinfo dki_info; 651*7c478bd9Sstevel@tonic-gate int md_flag = 0; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 654*7c478bd9Sstevel@tonic-gate if (efi_debug) 655*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "DKIOCINFO errno 0x%x\n", errno); 656*7c478bd9Sstevel@tonic-gate switch (errno) { 657*7c478bd9Sstevel@tonic-gate case EIO: 658*7c478bd9Sstevel@tonic-gate return (VT_EIO); 659*7c478bd9Sstevel@tonic-gate case EINVAL: 660*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 661*7c478bd9Sstevel@tonic-gate default: 662*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 663*7c478bd9Sstevel@tonic-gate } 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* check if we are dealing wih a metadevice */ 667*7c478bd9Sstevel@tonic-gate if ((strncmp(dki_info.dki_cname, "pseudo", 7) == 0) && 668*7c478bd9Sstevel@tonic-gate (strncmp(dki_info.dki_dname, "md", 3) == 0)) { 669*7c478bd9Sstevel@tonic-gate md_flag = 1; 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate if (check_input(vtoc)) { 673*7c478bd9Sstevel@tonic-gate /* 674*7c478bd9Sstevel@tonic-gate * not valid; if it's a metadevice just pass it down 675*7c478bd9Sstevel@tonic-gate * because SVM will do its own checking 676*7c478bd9Sstevel@tonic-gate */ 677*7c478bd9Sstevel@tonic-gate if (md_flag == 0) { 678*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = 1; 683*7c478bd9Sstevel@tonic-gate if (NBLOCKS(vtoc->efi_nparts, vtoc->efi_lbasize) < 34) { 684*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + vtoc->efi_lbasize; 685*7c478bd9Sstevel@tonic-gate } else { 686*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = NBLOCKS(vtoc->efi_nparts, 687*7c478bd9Sstevel@tonic-gate vtoc->efi_lbasize) * 688*7c478bd9Sstevel@tonic-gate vtoc->efi_lbasize; 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) 692*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate efi = dk_ioc.dki_data; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* stuff user's input into EFI struct */ 697*7c478bd9Sstevel@tonic-gate efi->efi_gpt_Signature = LE_64(EFI_SIGNATURE); 698*7c478bd9Sstevel@tonic-gate efi->efi_gpt_Revision = LE_32(vtoc->efi_version); /* 0x02000100 */ 699*7c478bd9Sstevel@tonic-gate efi->efi_gpt_HeaderSize = LE_32(sizeof (struct efi_gpt)); 700*7c478bd9Sstevel@tonic-gate efi->efi_gpt_Reserved1 = 0; 701*7c478bd9Sstevel@tonic-gate efi->efi_gpt_MyLBA = LE_64(1ULL); 702*7c478bd9Sstevel@tonic-gate efi->efi_gpt_AlternateLBA = LE_64(vtoc->efi_last_lba); 703*7c478bd9Sstevel@tonic-gate efi->efi_gpt_FirstUsableLBA = LE_64(vtoc->efi_first_u_lba); 704*7c478bd9Sstevel@tonic-gate efi->efi_gpt_LastUsableLBA = LE_64(vtoc->efi_last_u_lba); 705*7c478bd9Sstevel@tonic-gate efi->efi_gpt_PartitionEntryLBA = LE_64(2ULL); 706*7c478bd9Sstevel@tonic-gate efi->efi_gpt_NumberOfPartitionEntries = LE_32(vtoc->efi_nparts); 707*7c478bd9Sstevel@tonic-gate efi->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (struct efi_gpe)); 708*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT(efi->efi_gpt_DiskGUID, vtoc->efi_disk_uguid); 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate /* LINTED -- always longlong aligned */ 711*7c478bd9Sstevel@tonic-gate efi_parts = (efi_gpe_t *)((char *)dk_ioc.dki_data + sizeof (efi_gpt_t)); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate for (i = 0; i < vtoc->efi_nparts; i++) { 714*7c478bd9Sstevel@tonic-gate for (j = 0; 715*7c478bd9Sstevel@tonic-gate j < sizeof (conversion_array) / sizeof (struct uuid_to_ptag); 716*7c478bd9Sstevel@tonic-gate j++) { 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == j) { 719*7c478bd9Sstevel@tonic-gate UUID_LE_CONVERT( 720*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_PartitionTypeGUID, 721*7c478bd9Sstevel@tonic-gate conversion_array[j].uuid); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_StartingLBA = 725*7c478bd9Sstevel@tonic-gate LE_64(vtoc->efi_parts[i].p_start); 726*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_EndingLBA = 727*7c478bd9Sstevel@tonic-gate LE_64(vtoc->efi_parts[i].p_start + 728*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size - 1); 729*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_Attributes.PartitionAttrs = 730*7c478bd9Sstevel@tonic-gate LE_16(vtoc->efi_parts[i].p_flag); 731*7c478bd9Sstevel@tonic-gate for (j = 0; j < EFI_PART_NAME_LEN; j++) { 732*7c478bd9Sstevel@tonic-gate efi_parts[i].efi_gpe_PartitionName[j] = 733*7c478bd9Sstevel@tonic-gate LE_16((ushort_t)vtoc->efi_parts[i].p_name[j]); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_tag != V_UNASSIGNED) && 736*7c478bd9Sstevel@tonic-gate uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_uguid)) { 737*7c478bd9Sstevel@tonic-gate (void) uuid_generate((uchar_t *) 738*7c478bd9Sstevel@tonic-gate &vtoc->efi_parts[i].p_uguid); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate bcopy(&vtoc->efi_parts[i].p_uguid, 741*7c478bd9Sstevel@tonic-gate &efi_parts[i].efi_gpe_UniquePartitionGUID, 742*7c478bd9Sstevel@tonic-gate sizeof (uuid_t)); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate efi->efi_gpt_PartitionEntryArrayCRC32 = 745*7c478bd9Sstevel@tonic-gate LE_32(efi_crc32((unsigned char *)efi_parts, 746*7c478bd9Sstevel@tonic-gate vtoc->efi_nparts * (int)sizeof (struct efi_gpe))); 747*7c478bd9Sstevel@tonic-gate efi->efi_gpt_HeaderCRC32 = 748*7c478bd9Sstevel@tonic-gate LE_32(efi_crc32((unsigned char *)efi, sizeof (struct efi_gpt))); 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 751*7c478bd9Sstevel@tonic-gate free(dk_ioc.dki_data); 752*7c478bd9Sstevel@tonic-gate switch (errno) { 753*7c478bd9Sstevel@tonic-gate case EIO: 754*7c478bd9Sstevel@tonic-gate return (VT_EIO); 755*7c478bd9Sstevel@tonic-gate case EINVAL: 756*7c478bd9Sstevel@tonic-gate return (VT_EINVAL); 757*7c478bd9Sstevel@tonic-gate default: 758*7c478bd9Sstevel@tonic-gate return (VT_ERROR); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate /* if it's a metadevice we're done */ 762*7c478bd9Sstevel@tonic-gate if (md_flag) { 763*7c478bd9Sstevel@tonic-gate free(dk_ioc.dki_data); 764*7c478bd9Sstevel@tonic-gate return (0); 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate /* write backup partition array */ 767*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = vtoc->efi_last_u_lba + 1; 768*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length -= vtoc->efi_lbasize; 769*7c478bd9Sstevel@tonic-gate dk_ioc.dki_data++; 770*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 771*7c478bd9Sstevel@tonic-gate /* 772*7c478bd9Sstevel@tonic-gate * we wrote the primary label okay, so don't fail 773*7c478bd9Sstevel@tonic-gate */ 774*7c478bd9Sstevel@tonic-gate if (efi_debug) { 775*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 776*7c478bd9Sstevel@tonic-gate "write of backup partitions to block %llu " 777*7c478bd9Sstevel@tonic-gate "failed, errno %d\n", 778*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba + 1, 779*7c478bd9Sstevel@tonic-gate errno); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate /* 783*7c478bd9Sstevel@tonic-gate * now swap MyLBA and AlternateLBA fields and write backup 784*7c478bd9Sstevel@tonic-gate * partition table header 785*7c478bd9Sstevel@tonic-gate */ 786*7c478bd9Sstevel@tonic-gate dk_ioc.dki_lba = vtoc->efi_last_lba; 787*7c478bd9Sstevel@tonic-gate dk_ioc.dki_length = vtoc->efi_lbasize; 788*7c478bd9Sstevel@tonic-gate dk_ioc.dki_data--; 789*7c478bd9Sstevel@tonic-gate efi->efi_gpt_AlternateLBA = LE_64(1ULL); 790*7c478bd9Sstevel@tonic-gate efi->efi_gpt_MyLBA = LE_64(vtoc->efi_last_lba); 791*7c478bd9Sstevel@tonic-gate efi->efi_gpt_PartitionEntryLBA = LE_64(vtoc->efi_last_u_lba + 1); 792*7c478bd9Sstevel@tonic-gate efi->efi_gpt_HeaderCRC32 = 0; 793*7c478bd9Sstevel@tonic-gate efi->efi_gpt_HeaderCRC32 = 794*7c478bd9Sstevel@tonic-gate LE_32(efi_crc32((unsigned char *)dk_ioc.dki_data, 795*7c478bd9Sstevel@tonic-gate sizeof (struct efi_gpt))); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 798*7c478bd9Sstevel@tonic-gate if (efi_debug) { 799*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 800*7c478bd9Sstevel@tonic-gate "write of backup header to block %llu failed, " 801*7c478bd9Sstevel@tonic-gate "errno %d\n", 802*7c478bd9Sstevel@tonic-gate vtoc->efi_last_lba, 803*7c478bd9Sstevel@tonic-gate errno); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate /* write the PMBR */ 807*7c478bd9Sstevel@tonic-gate (void) write_pmbr(fd, vtoc); 808*7c478bd9Sstevel@tonic-gate if (ioctl(fd, MHIOCREREGISTERDEVID) == -1) { 809*7c478bd9Sstevel@tonic-gate if (efi_debug) { 810*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 811*7c478bd9Sstevel@tonic-gate "MHIOCREREGISTERDEVID failed %d\n", 812*7c478bd9Sstevel@tonic-gate errno); 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate free(dk_ioc.dki_data); 816*7c478bd9Sstevel@tonic-gate return (0); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate void 820*7c478bd9Sstevel@tonic-gate efi_free(struct dk_gpt *ptr) 821*7c478bd9Sstevel@tonic-gate { 822*7c478bd9Sstevel@tonic-gate free(ptr); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate /* 826*7c478bd9Sstevel@tonic-gate * Input: File descriptor 827*7c478bd9Sstevel@tonic-gate * Output: 1 if disk is >1TB OR has an EFI label, 0 otherwise. 828*7c478bd9Sstevel@tonic-gate */ 829*7c478bd9Sstevel@tonic-gate int 830*7c478bd9Sstevel@tonic-gate efi_type(int fd) 831*7c478bd9Sstevel@tonic-gate { 832*7c478bd9Sstevel@tonic-gate struct vtoc vtoc; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGVTOC, &vtoc) == -1) { 835*7c478bd9Sstevel@tonic-gate if (errno == ENOTSUP) { 836*7c478bd9Sstevel@tonic-gate return (1); 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate return (0); 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate void 843*7c478bd9Sstevel@tonic-gate efi_err_check(struct dk_gpt *vtoc) 844*7c478bd9Sstevel@tonic-gate { 845*7c478bd9Sstevel@tonic-gate int resv_part = -1; 846*7c478bd9Sstevel@tonic-gate int i, j; 847*7c478bd9Sstevel@tonic-gate diskaddr_t istart, jstart, isize, jsize, endsect; 848*7c478bd9Sstevel@tonic-gate int overlap = 0; 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate /* 851*7c478bd9Sstevel@tonic-gate * make sure no partitions overlap 852*7c478bd9Sstevel@tonic-gate */ 853*7c478bd9Sstevel@tonic-gate for (i = 0; i < vtoc->efi_nparts; i++) { 854*7c478bd9Sstevel@tonic-gate /* It can't be unassigned and have an actual size */ 855*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_tag == V_UNASSIGNED) && 856*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_size != 0)) { 857*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 858*7c478bd9Sstevel@tonic-gate "partition %d is \"unassigned\" but has a size " 859*7c478bd9Sstevel@tonic-gate "of %llu\n", i, vtoc->efi_parts[i].p_size); 860*7c478bd9Sstevel@tonic-gate } 861*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == V_UNASSIGNED) { 862*7c478bd9Sstevel@tonic-gate continue; 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_tag == V_RESERVED) { 865*7c478bd9Sstevel@tonic-gate if (resv_part != -1) { 866*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 867*7c478bd9Sstevel@tonic-gate "found duplicate reserved partition at " 868*7c478bd9Sstevel@tonic-gate "%d\n", i); 869*7c478bd9Sstevel@tonic-gate } 870*7c478bd9Sstevel@tonic-gate resv_part = i; 871*7c478bd9Sstevel@tonic-gate if (vtoc->efi_parts[i].p_size != EFI_MIN_RESV_SIZE) 872*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 873*7c478bd9Sstevel@tonic-gate "Warning: reserved partition size must " 874*7c478bd9Sstevel@tonic-gate "be %d sectors\n", EFI_MIN_RESV_SIZE); 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_start < vtoc->efi_first_u_lba) || 877*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_start > vtoc->efi_last_u_lba)) { 878*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 879*7c478bd9Sstevel@tonic-gate "Partition %d starts at %llu\n", 880*7c478bd9Sstevel@tonic-gate i, 881*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start); 882*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 883*7c478bd9Sstevel@tonic-gate "It must be between %llu and %llu.\n", 884*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba, 885*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate if ((vtoc->efi_parts[i].p_start + 888*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size < 889*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba) || 890*7c478bd9Sstevel@tonic-gate (vtoc->efi_parts[i].p_start + 891*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size > 892*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba + 1)) { 893*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 894*7c478bd9Sstevel@tonic-gate "Partition %d ends at %llu\n", 895*7c478bd9Sstevel@tonic-gate i, 896*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start + 897*7c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size); 898*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 899*7c478bd9Sstevel@tonic-gate "It must be between %llu and %llu.\n", 900*7c478bd9Sstevel@tonic-gate vtoc->efi_first_u_lba, 901*7c478bd9Sstevel@tonic-gate vtoc->efi_last_u_lba); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate for (j = 0; j < vtoc->efi_nparts; j++) { 905*7c478bd9Sstevel@tonic-gate isize = vtoc->efi_parts[i].p_size; 906*7c478bd9Sstevel@tonic-gate jsize = vtoc->efi_parts[j].p_size; 907*7c478bd9Sstevel@tonic-gate istart = vtoc->efi_parts[i].p_start; 908*7c478bd9Sstevel@tonic-gate jstart = vtoc->efi_parts[j].p_start; 909*7c478bd9Sstevel@tonic-gate if ((i != j) && (isize != 0) && (jsize != 0)) { 910*7c478bd9Sstevel@tonic-gate endsect = jstart + jsize -1; 911*7c478bd9Sstevel@tonic-gate if ((jstart <= istart) && 912*7c478bd9Sstevel@tonic-gate (istart <= endsect)) { 913*7c478bd9Sstevel@tonic-gate if (!overlap) { 914*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 915*7c478bd9Sstevel@tonic-gate "label error: EFI Labels do not " 916*7c478bd9Sstevel@tonic-gate "support overlapping partitions\n"); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 919*7c478bd9Sstevel@tonic-gate "Partition %d overlaps partition " 920*7c478bd9Sstevel@tonic-gate "%d.\n", i, j); 921*7c478bd9Sstevel@tonic-gate overlap = 1; 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate } 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate /* make sure there is a reserved partition */ 927*7c478bd9Sstevel@tonic-gate if (resv_part == -1) { 928*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 929*7c478bd9Sstevel@tonic-gate "no reserved partition found\n"); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * We need to get information necessary to construct a *new* efi 935*7c478bd9Sstevel@tonic-gate * label type 936*7c478bd9Sstevel@tonic-gate */ 937*7c478bd9Sstevel@tonic-gate int 938*7c478bd9Sstevel@tonic-gate efi_auto_sense(int fd, struct dk_gpt **vtoc) 939*7c478bd9Sstevel@tonic-gate { 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate int i; 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate /* 944*7c478bd9Sstevel@tonic-gate * Now build the default partition table 945*7c478bd9Sstevel@tonic-gate */ 946*7c478bd9Sstevel@tonic-gate if (efi_alloc_and_init(fd, EFI_NUMPAR, vtoc) != 0) { 947*7c478bd9Sstevel@tonic-gate if (efi_debug) { 948*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "efi_alloc_and_init failed.\n"); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate return (-1); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate for (i = 0; i < min((*vtoc)->efi_nparts, V_NUMPAR); i++) { 954*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[i].p_tag = default_vtoc_map[i].p_tag; 955*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[i].p_flag = default_vtoc_map[i].p_flag; 956*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[i].p_start = 0; 957*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[i].p_size = 0; 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate /* 960*7c478bd9Sstevel@tonic-gate * Make constants first 961*7c478bd9Sstevel@tonic-gate * and variable partitions later 962*7c478bd9Sstevel@tonic-gate */ 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate /* root partition - s0 128 MB */ 965*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[0].p_start = 34; 966*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[0].p_size = 262144; 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate /* partition - s1 128 MB */ 969*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[1].p_start = 262178; 970*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[1].p_size = 262144; 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* partition -s2 is NOT the Backup disk */ 973*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[2].p_tag = V_UNASSIGNED; 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate /* partition -s6 /usr partition - HOG */ 976*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[6].p_start = 524322; 977*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[6].p_size = (*vtoc)->efi_last_u_lba - 524322 978*7c478bd9Sstevel@tonic-gate - (1024 * 16); 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate /* efi reserved partition - s9 16K */ 981*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[8].p_start = (*vtoc)->efi_last_u_lba - (1024 * 16); 982*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[8].p_size = (1024 * 16); 983*7c478bd9Sstevel@tonic-gate (*vtoc)->efi_parts[8].p_tag = V_RESERVED; 984*7c478bd9Sstevel@tonic-gate return (0); 985*7c478bd9Sstevel@tonic-gate } 986