vdsk_common.c revision d84f0041660230c140a3895b8bfc7e428c7ccb1d
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/vdsk_common.h>
/*
* Hooks for EFI support
*/
/*
* This code provides generic functions to the vds and vdc drivers to read
* EFI labels from the disk backend and to get the EFI GPT and GPE. This is
* inspired from the libefi userland library and the cmlb driver. We will
* certainly be able to remove that code if RFE 6213117 is ever implemented.
*/
#ifdef DEBUG
static int vd_efi_debug = 0;
#else
#define VD_EFI_DEBUG(...)
#endif
(vdisk)->block_size)
static void
vd_efi_print(const char *format, ...)
{
}
/*
* Return a 32-bit CRC of the contents of the buffer.
*
* The seed is 0xffffffff and the result is XORed with 0xffffffff
* because this is what the Itanium firmware expects.
*/
unsigned int
vd_efi_crc32(const unsigned char *s, unsigned int len)
{
unsigned int crc32val;
return (crc32val ^ -1U);
}
static int
{
int status;
return (status);
}
/*
* Swap GPT data to match with the system endianness.
*/
static void
{
}
/*
* Swap GPE data to match with the system endianness.
*/
static void
{
int i, j;
for (i = 0; i < nparts; i++) {
for (j = 0; j < EFI_PART_NAME_LEN; j++) {
gpe[i].efi_gpe_PartitionName[j] =
}
}
}
/*
* Check that an EFI GPT is valid. This function should be called with a raw
* EFI GPT i.e. GPT data should be in little endian format as indicated in the
* EFI specification and they should not have been swapped to match with the
* system endianness.
*/
static int
{
VD_EFI_DEBUG("Bad EFI signature: 0x%llx != 0x%llx\n",
(long long)gpt->efi_gpt_Signature,
(long long)LE_64(EFI_SIGNATURE));
return (EINVAL);
}
/*
* check CRC of the header; the size of the header should
* never be larger than one block
*/
VD_EFI_DEBUG("Header size (%u bytes) larger than one block"
dev->block_size);
return (EINVAL);
}
if (crc_stored != crc_computed) {
VD_EFI_DEBUG("Bad EFI CRC: 0x%x != 0x%x\n",
return (EINVAL);
}
return (0);
}
/*
* Allocate and read the EFI GPT and GPE from the disk backend. Note that the
* on-disk GPT and GPE are stored in little endian format but this function
* returns them using the endianness of the system so that any field in the
* The caller is responsible for freeing the allocated structures by calling
* vd_efi_free().
*/
int
{
/*
* Read the EFI GPT.
*/
/*
* Because the DKIOCGETEFI ioctl was initially incorrectly
* implemented for a ZFS volume, the ioctl can fail with
* EINVAL if it is done on a ZFS volume managed by an old
* version of Solaris. This can happen if a ZFS volume is
* exported as a single-slice disk by a service domain
* running Solaris older than Solaris 10 Update 6.
*
* So we retry the ioctl to read both the GPT and the GPE at
* the same time accordingly to the old implementation.
*/
if (status == 0)
}
if (status != 0) {
goto errdone;
}
/*
* No valid label here; try the alternate. The alternate GPT is
* located in the last block of the disk.
*/
VD_EFI_DEBUG("DKIOCGETEFI (LBA=%lu) error %d\n",
goto errdone;
}
goto errdone;
VD_EFI_DEBUG("efi_read: primary label corrupt; using backup\n");
}
/* swap GPT data after checking the GPT is valid */
/*
* Read the EFI GPE.
*/
goto errdone;
}
if (nparts == 0) {
VD_EFI_DEBUG("No partition defined");
goto errdone;
}
/*
* The data variable is not NULL if we have used the old ioctl
* implementation for a ZFS volume. In that case, we only expect
* one partition and GPE data are already available in the data
* buffer, right after GPT data.
*/
if (nparts != 1) {
VD_EFI_DEBUG("Unexpected number of partitions (%u)",
nparts);
goto errdone;
}
} else {
VD_EFI_DEBUG("DKIOCGETEFI (GPE, LBA=%lu) error %d\n",
goto errdone;
}
}
if (status != 0) {
}
return (status);
}
/*
* Free the EFI GPE and GPT structures returned by vd_efi_alloc_and_read().
*/
void
{
}