Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <sys/crc32.h>
     28 #include <sys/cred.h>
     29 #include <sys/ddi.h>
     30 #include <sys/dkio.h>
     31 #include <sys/file.h>
     32 #include <sys/kmem.h>
     33 #include <sys/sunddi.h>
     34 #include <sys/sunldi.h>
     35 #include <sys/types.h>
     36 #include <sys/varargs.h>
     37 #include <sys/vtoc.h>
     38 
     39 #include <sys/vdsk_common.h>
     40 
     41 /*
     42  * Hooks for EFI support
     43  */
     44 
     45 /*
     46  * This code provides generic functions to the vds and vdc drivers to read
     47  * EFI labels from the disk backend and to get the EFI GPT and GPE. This is
     48  * inspired from the libefi userland library and the cmlb driver. We will
     49  * certainly be able to remove that code if RFE 6213117 is ever implemented.
     50  */
     51 
     52 #ifdef DEBUG
     53 
     54 #define	VD_EFI_DEBUG	if (vd_efi_debug) vd_efi_print
     55 
     56 static int vd_efi_debug = 0;
     57 
     58 #else
     59 
     60 #define	VD_EFI_DEBUG(...)
     61 
     62 #endif
     63 
     64 #define	VD_EFI_GPE_LEN(vdisk, nparts) \
     65 	((((sizeof (efi_gpe_t) * (nparts) - 1) / (vdisk)->block_size) + 1) * \
     66 	(vdisk)->block_size)
     67 
     68 static void
     69 vd_efi_print(const char *format, ...)
     70 {
     71 	va_list args;
     72 
     73 	va_start(args, format);
     74 	vcmn_err(CE_CONT, format, args);
     75 	va_end(args);
     76 }
     77 
     78 /*
     79  * Return a 32-bit CRC of the contents of the buffer.
     80  *
     81  * The seed is 0xffffffff and the result is XORed with 0xffffffff
     82  * because this is what the Itanium firmware expects.
     83  */
     84 unsigned int
     85 vd_efi_crc32(const unsigned char *s, unsigned int len)
     86 {
     87 	unsigned int crc32val;
     88 
     89 	CRC32(crc32val, s, len, -1U, crc32_table);
     90 
     91 	return (crc32val ^ -1U);
     92 }
     93 
     94 static int
     95 vd_efi_ioctl(vd_efi_dev_t *dev, int cmd, void *arg)
     96 {
     97 	int status;
     98 
     99 	ASSERT(dev->vdisk_ioctl != NULL);
    100 	ASSERT(dev->vdisk != NULL);
    101 	status = (*dev->vdisk_ioctl)(dev->vdisk, cmd, (uintptr_t)arg);
    102 
    103 	return (status);
    104 }
    105 
    106 /*
    107  * Swap GPT data to match with the system endianness.
    108  */
    109 static void
    110 vd_efi_swap_gpt(efi_gpt_t *gpt)
    111 {
    112 	gpt->efi_gpt_Signature = LE_64(gpt->efi_gpt_Signature);
    113 	gpt->efi_gpt_Revision = LE_32(gpt->efi_gpt_Revision);
    114 	gpt->efi_gpt_HeaderSize = LE_32(gpt->efi_gpt_HeaderSize);
    115 	gpt->efi_gpt_HeaderCRC32 = LE_32(gpt->efi_gpt_HeaderCRC32);
    116 	gpt->efi_gpt_MyLBA = LE_64(gpt->efi_gpt_MyLBA);
    117 	gpt->efi_gpt_AlternateLBA = LE_64(gpt->efi_gpt_AlternateLBA);
    118 	gpt->efi_gpt_FirstUsableLBA = LE_64(gpt->efi_gpt_FirstUsableLBA);
    119 	gpt->efi_gpt_LastUsableLBA = LE_64(gpt->efi_gpt_LastUsableLBA);
    120 	UUID_LE_CONVERT(gpt->efi_gpt_DiskGUID, gpt->efi_gpt_DiskGUID);
    121 	gpt->efi_gpt_PartitionEntryLBA = LE_64(gpt->efi_gpt_PartitionEntryLBA);
    122 	gpt->efi_gpt_NumberOfPartitionEntries =
    123 	    LE_32(gpt->efi_gpt_NumberOfPartitionEntries);
    124 	gpt->efi_gpt_SizeOfPartitionEntry =
    125 	    LE_32(gpt->efi_gpt_SizeOfPartitionEntry);
    126 	gpt->efi_gpt_PartitionEntryArrayCRC32 =
    127 	    LE_32(gpt->efi_gpt_PartitionEntryArrayCRC32);
    128 }
    129 
    130 /*
    131  * Swap GPE data to match with the system endianness.
    132  */
    133 static void
    134 vd_efi_swap_gpe(efi_gpe_t *gpe, int nparts)
    135 {
    136 	int i, j;
    137 
    138 	for (i = 0; i < nparts; i++) {
    139 		UUID_LE_CONVERT(gpe[i].efi_gpe_PartitionTypeGUID,
    140 		    gpe[i].efi_gpe_PartitionTypeGUID);
    141 		UUID_LE_CONVERT(gpe[i].efi_gpe_UniquePartitionGUID,
    142 		    gpe[i].efi_gpe_UniquePartitionGUID);
    143 		gpe[i].efi_gpe_StartingLBA = LE_64(gpe[i].efi_gpe_StartingLBA);
    144 		gpe[i].efi_gpe_EndingLBA = LE_64(gpe[i].efi_gpe_EndingLBA);
    145 		gpe[i].efi_gpe_Attributes.PartitionAttrs =
    146 		    LE_16(gpe[i].efi_gpe_Attributes.PartitionAttrs);
    147 		for (j = 0; j < EFI_PART_NAME_LEN; j++) {
    148 			gpe[i].efi_gpe_PartitionName[j] =
    149 			    LE_16(gpe[i].efi_gpe_PartitionName[j]);
    150 		}
    151 	}
    152 }
    153 
    154 /*
    155  * Check that an EFI GPT is valid. This function should be called with a raw
    156  * EFI GPT i.e. GPT data should be in little endian format as indicated in the
    157  * EFI specification and they should not have been swapped to match with the
    158  * system endianness.
    159  */
    160 static int
    161 vd_efi_check_gpt(vd_efi_dev_t *dev, efi_gpt_t *gpt)
    162 {
    163 	uint_t crc_stored, crc_computed;
    164 
    165 	if (gpt->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) {
    166 		VD_EFI_DEBUG("Bad EFI signature: 0x%llx != 0x%llx\n",
    167 		    (long long)gpt->efi_gpt_Signature,
    168 		    (long long)LE_64(EFI_SIGNATURE));
    169 		return (EINVAL);
    170 	}
    171 
    172 	/*
    173 	 * check CRC of the header; the size of the header should
    174 	 * never be larger than one block
    175 	 */
    176 	if (LE_32(gpt->efi_gpt_HeaderSize) > dev->block_size) {
    177 		VD_EFI_DEBUG("Header size (%u bytes) larger than one block"
    178 		    "(%u bytes)\n", LE_32(gpt->efi_gpt_HeaderSize),
    179 		    dev->block_size);
    180 		return (EINVAL);
    181 	}
    182 
    183 	crc_stored = LE_32(gpt->efi_gpt_HeaderCRC32);
    184 	gpt->efi_gpt_HeaderCRC32 = LE_32(0);
    185 	crc_computed = vd_efi_crc32((unsigned char *)gpt,
    186 	    LE_32(gpt->efi_gpt_HeaderSize));
    187 	gpt->efi_gpt_HeaderCRC32 = LE_32(crc_stored);
    188 
    189 	if (crc_stored != crc_computed) {
    190 		VD_EFI_DEBUG("Bad EFI CRC: 0x%x != 0x%x\n",
    191 		    crc_stored, crc_computed);
    192 			return (EINVAL);
    193 	}
    194 
    195 	return (0);
    196 }
    197 
    198 /*
    199  * Allocate and read the EFI GPT and GPE from the disk backend. Note that the
    200  * on-disk GPT and GPE are stored in little endian format but this function
    201  * returns them using the endianness of the system so that any field in the
    202  * GPT/GPE structures can be directly accessible without any further conversion.
    203  * The caller is responsible for freeing the allocated structures by calling
    204  * vd_efi_free().
    205  */
    206 int
    207 vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **efi_gpt,
    208     efi_gpe_t **efi_gpe)
    209 {
    210 	dk_efi_t		dk_efi;
    211 	efi_gpt_t		*gpt = NULL;
    212 	efi_gpe_t		*gpe = NULL;
    213 	efi_gpt_t		*data = NULL;
    214 	size_t			gpt_len, gpe_len, data_len;
    215 	int 			nparts, status;
    216 
    217 	ASSERT(dev->block_size >= sizeof (efi_gpt_t));
    218 	gpt_len = dev->block_size;
    219 	gpt = kmem_zalloc(gpt_len, KM_SLEEP);
    220 
    221 	/*
    222 	 * Read the EFI GPT.
    223 	 */
    224 	dk_efi.dki_lba = 1;
    225 	dk_efi.dki_data = gpt;
    226 	dk_efi.dki_length = gpt_len;
    227 
    228 	status = vd_efi_ioctl(dev, DKIOCGETEFI, &dk_efi);
    229 
    230 	if (status == EINVAL) {
    231 		/*
    232 		 * Because the DKIOCGETEFI ioctl was initially incorrectly
    233 		 * implemented for a ZFS volume, the ioctl can fail with
    234 		 * EINVAL if it is done on a ZFS volume managed by an old
    235 		 * version of Solaris. This can happen if a ZFS volume is
    236 		 * exported as a single-slice disk by a service domain
    237 		 * running Solaris older than Solaris 10 Update 6.
    238 		 *
    239 		 * So we retry the ioctl to read both the GPT and the GPE at
    240 		 * the same time accordingly to the old implementation.
    241 		 */
    242 		data_len = sizeof (efi_gpt_t) + sizeof (efi_gpe_t);
    243 		data = kmem_zalloc(data_len, KM_SLEEP);
    244 
    245 		dk_efi.dki_lba = 1;
    246 		dk_efi.dki_data = data;
    247 		dk_efi.dki_length = data_len;
    248 		status = vd_efi_ioctl(dev, DKIOCGETEFI, &dk_efi);
    249 
    250 		if (status == 0)
    251 			bcopy(data, gpt, sizeof (efi_gpt_t));
    252 	}
    253 
    254 	if (status != 0) {
    255 		VD_EFI_DEBUG("DKIOCGETEFI (GPT, LBA=1) error %d\n", status);
    256 		goto errdone;
    257 	}
    258 
    259 	if ((status = vd_efi_check_gpt(dev, gpt)) != 0) {
    260 		/*
    261 		 * No valid label here; try the alternate. The alternate GPT is
    262 		 * located in the last block of the disk.
    263 		 */
    264 		dk_efi.dki_lba = dev->disk_size - 1;
    265 		dk_efi.dki_data = gpt;
    266 		dk_efi.dki_length = gpt_len;
    267 
    268 		if ((status = vd_efi_ioctl(dev, DKIOCGETEFI, &dk_efi)) != 0) {
    269 			VD_EFI_DEBUG("DKIOCGETEFI (LBA=%lu) error %d\n",
    270 			    dev->disk_size - 1, status);
    271 			goto errdone;
    272 		}
    273 
    274 		if ((status = vd_efi_check_gpt(dev, gpt)) != 0)
    275 			goto errdone;
    276 
    277 		VD_EFI_DEBUG("efi_read: primary label corrupt; using backup\n");
    278 	}
    279 
    280 	/* swap GPT data after checking the GPT is valid */
    281 	vd_efi_swap_gpt(gpt);
    282 
    283 	/*
    284 	 * Read the EFI GPE.
    285 	 */
    286 	nparts = gpt->efi_gpt_NumberOfPartitionEntries;
    287 
    288 	if (nparts > NDKMAP + 1) {
    289 		VD_EFI_DEBUG("Too many EFI partitions (%u)", nparts);
    290 		status = EINVAL;
    291 		goto errdone;
    292 	}
    293 
    294 	if (nparts == 0) {
    295 		VD_EFI_DEBUG("No partition defined");
    296 		status = EINVAL;
    297 		goto errdone;
    298 	}
    299 
    300 	gpe_len = VD_EFI_GPE_LEN(dev, nparts);
    301 	gpe = kmem_zalloc(gpe_len, KM_SLEEP);
    302 
    303 	if (data != NULL) {
    304 		/*
    305 		 * The data variable is not NULL if we have used the old ioctl
    306 		 * implementation for a ZFS volume. In that case, we only expect
    307 		 * one partition and GPE data are already available in the data
    308 		 * buffer, right after GPT data.
    309 		 */
    310 		if (nparts != 1) {
    311 			VD_EFI_DEBUG("Unexpected number of partitions (%u)",
    312 			    nparts);
    313 			status = EINVAL;
    314 			goto errdone;
    315 		}
    316 
    317 		bcopy(data + 1, gpe, sizeof (efi_gpe_t));
    318 
    319 	} else {
    320 		dk_efi.dki_lba = gpt->efi_gpt_PartitionEntryLBA;
    321 		dk_efi.dki_data = (efi_gpt_t *)gpe;
    322 		dk_efi.dki_length = gpe_len;
    323 
    324 		if ((status = vd_efi_ioctl(dev, DKIOCGETEFI, &dk_efi)) != 0) {
    325 			VD_EFI_DEBUG("DKIOCGETEFI (GPE, LBA=%lu) error %d\n",
    326 			    gpt->efi_gpt_PartitionEntryLBA, status);
    327 			goto errdone;
    328 		}
    329 	}
    330 
    331 	vd_efi_swap_gpe(gpe, nparts);
    332 
    333 	*efi_gpt = gpt;
    334 	*efi_gpe = gpe;
    335 
    336 errdone:
    337 
    338 	if (data != NULL)
    339 		kmem_free(data, data_len);
    340 
    341 	if (status != 0) {
    342 		if (gpe != NULL)
    343 			kmem_free(gpe, gpe_len);
    344 		if (gpt != NULL)
    345 			kmem_free(gpt, gpt_len);
    346 	}
    347 
    348 	return (status);
    349 }
    350 
    351 /*
    352  * Free the EFI GPE and GPT structures returned by vd_efi_alloc_and_read().
    353  */
    354 void
    355 vd_efi_free(vd_efi_dev_t *dev, efi_gpt_t *gpt, efi_gpe_t *gpe)
    356 {
    357 	kmem_free(gpe, VD_EFI_GPE_LEN(dev,
    358 	    gpt->efi_gpt_NumberOfPartitionEntries));
    359 	kmem_free(gpt, dev->block_size);
    360 }
    361