/* $Id$ */
/** @file
* IPRT Disk Volume Management API (DVM) - GPT format backend.
*/
/*
* Copyright (C) 2011-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** The GPT signature. */
/**
* GPT on disk header.
*/
#pragma pack(1)
typedef struct GptHdr
{
/** Signature ("EFI PART"). */
/** Revision. */
/** Header size. */
/** CRC of header. */
} GptHdr;
/** Pointer to a GPT header. */
#pragma pack()
/**
* Complete GPT table header for revision 1.0.
*/
#pragma pack(1)
typedef struct GptHdrRev1
{
/** Header. */
/** Reserved. */
/** Current LBA. */
/** Backup LBA. */
/** First usable LBA for partitions. */
/** Last usable LBA for partitions. */
/** Disk UUID. */
/** LBA of first partition entry. */
/** Number of partition entries. */
/** Partition entry size. */
/** CRC of partition entries. */
} GptHdrRev1;
/** Pointer to a revision 1.0 GPT header. */
#pragma pack()
/**
* GPT partition table entry.
*/
#pragma pack(1)
typedef struct GptEntry
{
/** Partition type UUID. */
/** Partition UUID. */
/** First LBA. */
/** Last LBA. */
/** Attribute flags. */
/** Partition name (UTF-16LE code units). */
} GptEntry;
/** Pointer to a GPT entry. */
#pragma pack()
/** Partition flags - System partition. */
/** Partition flags - Partition is readonly. */
/** Partition flags - Partition is hidden. */
/** Partition flags - Don't automount this partition. */
/**
* GPT volume manager data.
*/
typedef struct RTDVMFMTINTERNAL
{
/** Pointer to the underlying disk. */
/** GPT header. */
/** GPT array. */
/** Number of occupied partition entries. */
/** Pointer to the MBR volume manager. */
/**
* GPT volume data.
*/
typedef struct RTDVMVOLUMEFMTINTERNAL
{
/** Pointer to the volume manager. */
/** Partition table entry index. */
/** Start offset of the volume. */
/** Size of the volume. */
/** Pointer to the GPT entry in the array. */
/** Pointer to an MBR volume. */
/**
* GPT partition type to DVM volume type mapping entry.
*/
typedef struct RTDVMGPTPARTTYPE2VOLTYPE
{
/** Type UUID. */
const char *pcszUuid;
/** DVM volume type. */
/** Pointer to a MBR FS Type to volume type mapping entry. */
/** Converts a LBA number to the byte offset. */
/** Converts a Byte offset to the LBA number. */
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/**
* Mapping of partition types to DVM volume types.
*
*/
{
{"0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", RTDVMVOLTYPE_LINUX_SWAP},
{"EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", RTDVMVOLTYPE_LINUX_NATIVE},
{"E6D6D379-F507-44C2-A23C-238F2A3DF928", RTDVMVOLTYPE_LINUX_LVM},
{"A19D880F-05FC-4D3B-A006-743F0F84911E", RTDVMVOLTYPE_LINUX_SOFTRAID},
{"48465300-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_MAC_OSX_HFS},
};
{
{
/* Read from the disk and check for the signature. */
if ( RT_SUCCESS(rc)
}
return rc;
}
{
if (pThis)
{
pThis->cPartitions = 0;
/* Read the complete GPT header and convert to host endianess. */
if (RT_SUCCESS(rc))
{
/** @todo: Disk UUID */
{
pThis->paGptEntries = (PGptEntry)RTMemAllocZ(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);
if (pThis->paGptEntries)
{
if (RT_SUCCESS(rc))
{
/* Count the occupied entries. */
{
/* Convert to host endianess. */
/** @todo: Uuids */
pThis->paGptEntries[i].aPartitionName[cwc] = RT_LE2H_U16(pThis->paGptEntries[i].aPartitionName[cwc]);
pThis->cPartitions++;
}
}
if (RT_FAILURE(rc))
}
else
rc = VERR_NO_MEMORY;
}
else
if (RT_SUCCESS(rc))
*phVolMgrFmt = pThis;
else
}
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
return VERR_NOT_IMPLEMENTED;
}
{
}
bool *pfUsed)
{
*pfUsed = true;
else
*pfUsed = false;
return VINF_SUCCESS;
}
{
return pThis->cPartitions;
}
{
}
/**
* Creates a new volume.
*
* @returns IPRT status code.
* @param pThis The MBR volume manager data.
* @param pGptEntry The GPT entry.
* @param idx The index in the partition array.
* @param phVolFmt Where to store the volume data on success.
*/
{
PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL));
if (pVol)
{
pVol->cbVolume = RTDVM_GPT_LBA2BYTE(pGptEntry->u64LbaLast - pGptEntry->u64LbaFirst + 1, pThis->pDisk);
}
else
rc = VERR_NO_MEMORY;
return rc;
}
{
if (pThis->cPartitions != 0)
{
/* Search for the first non empty entry. */
{
{
break;
}
pGptEntry++;
}
}
else
return rc;
}
static DECLCALLBACK(int) rtDvmFmtGptQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext)
{
{
{
break;
}
pGptEntry++;
}
return rc;
}
{
}
{
}
{
*ppszVolName = NULL;
rc = RTUtf16ToUtf8Ex(&pVol->pGptEntry->aPartitionName[0], RT_ELEMENTS(pVol->pGptEntry->aPartitionName),
ppszVolName, 0, NULL);
return rc;
}
{
for (unsigned i = 0; i < RT_ELEMENTS(g_aPartType2DvmVolTypes); i++)
{
break;
}
return enmVolType;
}
{
return 0;
}
{
bool fIntersect = false;
{
fIntersect = true;
}
return fIntersect;
}
static DECLCALLBACK(int) rtDvmFmtGptVolumeRead(RTDVMVOLUMEFMT hVolFmt, uint64_t off, void *pvBuf, size_t cbRead)
{
}
static DECLCALLBACK(int) rtDvmFmtGptVolumeWrite(RTDVMVOLUMEFMT hVolFmt, uint64_t off, const void *pvBuf, size_t cbWrite)
{
}
{
/* pcszFmt */
"GPT",
/* pfnProbe */
/* pfnOpen */
/* pfnInitialize */
/* pfnClose */
/* pfnQueryRangeUse */
/* pfnGetValidVolumes */
/* pfnGetMaxVolumes */
/* pfnQueryFirstVolume */
/* pfnQueryNextVolume */
/* pfnVolumeClose */
/* pfnVolumeGetSize */
/* pfnVolumeQueryName */
/* pfnVolumeGetType */
/* pfnVolumeGetFlags */
/* pfnVolumeIsRangeIntersecting */
/* pfnVolumeRead */
/* pfnVolumeWrite */
};