[36868] | 1 | /* $Id: dvmgpt.cpp 99989 2023-05-26 12:06:12Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * IPRT Disk Volume Management API (DVM) - GPT format backend.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2011-2023 Oracle and/or its affiliates.
|
---|
[36868] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
[36868] | 11 | *
|
---|
[96407] | 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
[36868] | 25 | * The contents of this file may alternatively be used under the terms
|
---|
| 26 | * of the Common Development and Distribution License Version 1.0
|
---|
[96407] | 27 | * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
|
---|
| 28 | * in the VirtualBox distribution, in which case the provisions of the
|
---|
[36868] | 29 | * CDDL are applicable instead of those of the GPL.
|
---|
| 30 | *
|
---|
| 31 | * You may elect to license modified versions of this file under the
|
---|
| 32 | * terms and conditions of either the GPL or the CDDL or both.
|
---|
[96407] | 33 | *
|
---|
| 34 | * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
|
---|
[36868] | 35 | */
|
---|
| 36 |
|
---|
[37024] | 37 |
|
---|
[57358] | 38 | /*********************************************************************************************************************************
|
---|
| 39 | * Header Files *
|
---|
| 40 | *********************************************************************************************************************************/
|
---|
[76408] | 41 | #include <iprt/dvm.h>
|
---|
| 42 |
|
---|
[36868] | 43 | #include <iprt/assert.h>
|
---|
[76408] | 44 | #include <iprt/asm.h>
|
---|
[36868] | 45 | #include <iprt/mem.h>
|
---|
| 46 | #include <iprt/string.h>
|
---|
[76408] | 47 | #include <iprt/utf16.h>
|
---|
[36868] | 48 | #include <iprt/uuid.h>
|
---|
| 49 | #include "internal/dvm.h"
|
---|
| 50 |
|
---|
[37024] | 51 |
|
---|
[57358] | 52 | /*********************************************************************************************************************************
|
---|
| 53 | * Structures and Typedefs *
|
---|
| 54 | *********************************************************************************************************************************/
|
---|
[36868] | 55 | /** The GPT signature. */
|
---|
| 56 | #define RTDVM_GPT_SIGNATURE "EFI PART"
|
---|
| 57 |
|
---|
| 58 | /**
|
---|
| 59 | * GPT on disk header.
|
---|
| 60 | */
|
---|
[69609] | 61 | typedef struct GPTHDR
|
---|
[36868] | 62 | {
|
---|
[69609] | 63 | /** 0x00: Signature ("EFI PART"). */
|
---|
[36868] | 64 | char abSignature[8];
|
---|
[69609] | 65 | /** 0x08: Revision. */
|
---|
[36868] | 66 | uint32_t u32Revision;
|
---|
[69609] | 67 | /** 0x0c: Header size. */
|
---|
[36868] | 68 | uint32_t cbHeader;
|
---|
[69609] | 69 | /** 0x10: CRC of header. */
|
---|
[36868] | 70 | uint32_t u32Crc;
|
---|
[69609] | 71 | } GPTHDR;
|
---|
[36868] | 72 | /** Pointer to a GPT header. */
|
---|
[69609] | 73 | typedef struct GPTHDR *PGPTHDR;
|
---|
| 74 | AssertCompileSize(GPTHDR, 20);
|
---|
[36868] | 75 |
|
---|
| 76 | /**
|
---|
| 77 | * Complete GPT table header for revision 1.0.
|
---|
| 78 | */
|
---|
| 79 | #pragma pack(1)
|
---|
[69609] | 80 | typedef struct GPTHDRREV1
|
---|
[36868] | 81 | {
|
---|
[69609] | 82 | /** 0x00: Header. */
|
---|
| 83 | GPTHDR Hdr;
|
---|
| 84 | /** 0x14: Reserved. */
|
---|
[36868] | 85 | uint32_t u32Reserved;
|
---|
[69609] | 86 | /** 0x18: Current LBA. */
|
---|
[36868] | 87 | uint64_t u64LbaCurrent;
|
---|
[69609] | 88 | /** 0x20: Backup LBA. */
|
---|
[36868] | 89 | uint64_t u64LbaBackup;
|
---|
[69609] | 90 | /** 0x28:First usable LBA for partitions. */
|
---|
[36868] | 91 | uint64_t u64LbaFirstPartition;
|
---|
[69609] | 92 | /** 0x30: Last usable LBA for partitions. */
|
---|
[36868] | 93 | uint64_t u64LbaLastPartition;
|
---|
[69609] | 94 | /** 0x38: Disk UUID. */
|
---|
[36868] | 95 | RTUUID DiskUuid;
|
---|
[69609] | 96 | /** 0x48: LBA of first partition entry. */
|
---|
[36868] | 97 | uint64_t u64LbaPartitionEntries;
|
---|
[69609] | 98 | /** 0x50: Number of partition entries. */
|
---|
[36868] | 99 | uint32_t cPartitionEntries;
|
---|
[69609] | 100 | /** 0x54: Partition entry size. */
|
---|
[36868] | 101 | uint32_t cbPartitionEntry;
|
---|
[69609] | 102 | /** 0x58: CRC of partition entries. */
|
---|
[36868] | 103 | uint32_t u32CrcPartitionEntries;
|
---|
[69609] | 104 | } GPTHDRREV1;
|
---|
[36868] | 105 | /** Pointer to a revision 1.0 GPT header. */
|
---|
[69609] | 106 | typedef GPTHDRREV1 *PGPTHDRREV1;
|
---|
[36868] | 107 | #pragma pack()
|
---|
[69609] | 108 | AssertCompileSize(GPTHDRREV1, 92);
|
---|
[36868] | 109 |
|
---|
| 110 | /**
|
---|
| 111 | * GPT partition table entry.
|
---|
| 112 | */
|
---|
[69609] | 113 | typedef struct GPTENTRY
|
---|
[36868] | 114 | {
|
---|
[69609] | 115 | /** 0x00: Partition type UUID. */
|
---|
[36868] | 116 | RTUUID UuidType;
|
---|
[69609] | 117 | /** 0x10: Partition UUID. */
|
---|
[36868] | 118 | RTUUID UuidPartition;
|
---|
[69609] | 119 | /** 0x20: First LBA. */
|
---|
[36868] | 120 | uint64_t u64LbaFirst;
|
---|
[69609] | 121 | /** 0x28: Last LBA. */
|
---|
[36868] | 122 | uint64_t u64LbaLast;
|
---|
[69609] | 123 | /** 0x30: Attribute flags. */
|
---|
[36868] | 124 | uint64_t u64Flags;
|
---|
[69609] | 125 | /** 0x38: Partition name (UTF-16LE code units). */
|
---|
[36868] | 126 | RTUTF16 aPartitionName[36];
|
---|
[69609] | 127 | } GPTENTRY;
|
---|
[36868] | 128 | /** Pointer to a GPT entry. */
|
---|
[69609] | 129 | typedef struct GPTENTRY *PGPTENTRY;
|
---|
| 130 | AssertCompileSize(GPTENTRY, 128);
|
---|
[36868] | 131 |
|
---|
| 132 | /** Partition flags - System partition. */
|
---|
| 133 | #define RTDVM_GPT_ENTRY_SYSTEM RT_BIT_64(0)
|
---|
| 134 | /** Partition flags - Partition is readonly. */
|
---|
| 135 | #define RTDVM_GPT_ENTRY_READONLY RT_BIT_64(60)
|
---|
| 136 | /** Partition flags - Partition is hidden. */
|
---|
| 137 | #define RTDVM_GPT_ENTRY_HIDDEN RT_BIT_64(62)
|
---|
| 138 | /** Partition flags - Don't automount this partition. */
|
---|
| 139 | #define RTDVM_GPT_ENTRY_NO_AUTOMOUNT RT_BIT_64(63)
|
---|
| 140 |
|
---|
| 141 | /**
|
---|
| 142 | * GPT volume manager data.
|
---|
| 143 | */
|
---|
| 144 | typedef struct RTDVMFMTINTERNAL
|
---|
| 145 | {
|
---|
| 146 | /** Pointer to the underlying disk. */
|
---|
| 147 | PCRTDVMDISK pDisk;
|
---|
| 148 | /** GPT header. */
|
---|
[69609] | 149 | GPTHDRREV1 HdrRev1;
|
---|
[36868] | 150 | /** GPT array. */
|
---|
[69609] | 151 | PGPTENTRY paGptEntries;
|
---|
[36868] | 152 | /** Number of occupied partition entries. */
|
---|
| 153 | uint32_t cPartitions;
|
---|
| 154 | } RTDVMFMTINTERNAL;
|
---|
| 155 | /** Pointer to the MBR volume manager. */
|
---|
| 156 | typedef RTDVMFMTINTERNAL *PRTDVMFMTINTERNAL;
|
---|
| 157 |
|
---|
| 158 | /**
|
---|
| 159 | * GPT volume data.
|
---|
| 160 | */
|
---|
| 161 | typedef struct RTDVMVOLUMEFMTINTERNAL
|
---|
| 162 | {
|
---|
| 163 | /** Pointer to the volume manager. */
|
---|
| 164 | PRTDVMFMTINTERNAL pVolMgr;
|
---|
| 165 | /** Partition table entry index. */
|
---|
| 166 | uint32_t idxEntry;
|
---|
| 167 | /** Start offset of the volume. */
|
---|
| 168 | uint64_t offStart;
|
---|
| 169 | /** Size of the volume. */
|
---|
| 170 | uint64_t cbVolume;
|
---|
| 171 | /** Pointer to the GPT entry in the array. */
|
---|
[69609] | 172 | PGPTENTRY pGptEntry;
|
---|
[36868] | 173 | } RTDVMVOLUMEFMTINTERNAL;
|
---|
| 174 | /** Pointer to an MBR volume. */
|
---|
| 175 | typedef RTDVMVOLUMEFMTINTERNAL *PRTDVMVOLUMEFMTINTERNAL;
|
---|
| 176 |
|
---|
| 177 | /**
|
---|
| 178 | * GPT partition type to DVM volume type mapping entry.
|
---|
| 179 | */
|
---|
| 180 |
|
---|
| 181 | typedef struct RTDVMGPTPARTTYPE2VOLTYPE
|
---|
| 182 | {
|
---|
| 183 | /** Type UUID. */
|
---|
| 184 | const char *pcszUuid;
|
---|
| 185 | /** DVM volume type. */
|
---|
| 186 | RTDVMVOLTYPE enmVolType;
|
---|
| 187 | } RTDVMGPTPARTTYPE2VOLTYPE;
|
---|
| 188 | /** Pointer to a MBR FS Type to volume type mapping entry. */
|
---|
| 189 | typedef RTDVMGPTPARTTYPE2VOLTYPE *PRTDVMGPTPARTTYPE2VOLTYPE;
|
---|
| 190 |
|
---|
| 191 | /** Converts a LBA number to the byte offset. */
|
---|
| 192 | #define RTDVM_GPT_LBA2BYTE(lba, disk) ((lba) * (disk)->cbSector)
|
---|
| 193 | /** Converts a Byte offset to the LBA number. */
|
---|
| 194 | #define RTDVM_GPT_BYTE2LBA(lba, disk) ((lba) / (disk)->cbSector)
|
---|
| 195 |
|
---|
[37024] | 196 |
|
---|
[57358] | 197 | /*********************************************************************************************************************************
|
---|
| 198 | * Global Variables *
|
---|
| 199 | *********************************************************************************************************************************/
|
---|
[36868] | 200 | /**
|
---|
| 201 | * Mapping of partition types to DVM volume types.
|
---|
| 202 | *
|
---|
| 203 | * From http://en.wikipedia.org/wiki/GUID_Partition_Table
|
---|
| 204 | */
|
---|
| 205 | static const RTDVMGPTPARTTYPE2VOLTYPE g_aPartType2DvmVolTypes[] =
|
---|
| 206 | {
|
---|
[73156] | 207 | { "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", RTDVMVOLTYPE_EFI_SYSTEM },
|
---|
[36868] | 208 |
|
---|
[73156] | 209 | { "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", RTDVMVOLTYPE_WIN_BASIC },
|
---|
| 210 | { "E3C9E316-0B5C-4DB8-817D-F92DF00215AE", RTDVMVOLTYPE_WIN_MSR },
|
---|
| 211 | { "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", RTDVMVOLTYPE_WIN_LDM_META },
|
---|
| 212 | { "AF9B60A0-1431-4F62-BC68-3311714A69AD", RTDVMVOLTYPE_WIN_LDM_DATA },
|
---|
| 213 | { "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", RTDVMVOLTYPE_WIN_RECOVERY },
|
---|
| 214 | { "E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D", RTDVMVOLTYPE_WIN_STORAGE_SPACES },
|
---|
[36868] | 215 |
|
---|
[73156] | 216 | { "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", RTDVMVOLTYPE_LINUX_SWAP },
|
---|
| 217 | { "0FC63DAF-8483-4772-8E79-3D69D8477DE4", RTDVMVOLTYPE_LINUX_NATIVE },
|
---|
| 218 | { "44479540-F297-41B2-9AF7-D131D5F0458A", RTDVMVOLTYPE_LINUX_NATIVE }, /* x86 root */
|
---|
| 219 | { "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709", RTDVMVOLTYPE_LINUX_NATIVE }, /* AMD64 root */
|
---|
| 220 | { "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3", RTDVMVOLTYPE_LINUX_NATIVE }, /* ARM32 root */
|
---|
| 221 | { "B921B045-1DF0-41C3-AF44-4C6F280D3FAE", RTDVMVOLTYPE_LINUX_NATIVE }, /* ARM64 root */
|
---|
| 222 | { "E6D6D379-F507-44C2-A23C-238F2A3DF928", RTDVMVOLTYPE_LINUX_LVM },
|
---|
| 223 | { "A19D880F-05FC-4D3B-A006-743F0F84911E", RTDVMVOLTYPE_LINUX_SOFTRAID },
|
---|
[36868] | 224 |
|
---|
[73156] | 225 | { "83BD6B9D-7F41-11DC-BE0B-001560B84F0F", RTDVMVOLTYPE_FREEBSD }, /* Boot */
|
---|
| 226 | { "516E7CB4-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Data */
|
---|
| 227 | { "516E7CB5-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Swap */
|
---|
| 228 | { "516E7CB6-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* UFS */
|
---|
| 229 | { "516E7CB8-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Vinum */
|
---|
| 230 | { "516E7CBA-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* ZFS */
|
---|
[36868] | 231 |
|
---|
[73156] | 232 | { "49F48D32-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Swap */
|
---|
| 233 | { "49F48D5A-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* FFS */
|
---|
| 234 | { "49F48D82-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* LFS */
|
---|
| 235 | { "49F48DAA-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Raid */
|
---|
| 236 | { "2DB519C4-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Concatenated */
|
---|
| 237 | { "2DB519EC-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Encrypted */
|
---|
| 238 |
|
---|
| 239 | { "48465300-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_DARWIN_HFS },
|
---|
| 240 | { "7C3457EF-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_DARWIN_APFS },
|
---|
| 241 |
|
---|
| 242 | { "6A82CB45-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Boot */
|
---|
| 243 | { "6A85CF4D-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Root */
|
---|
| 244 | { "6A87C46F-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Swap */
|
---|
| 245 | { "6A8B642B-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Backup */
|
---|
| 246 | { "6A898CC3-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /usr */
|
---|
| 247 | { "6A8EF2E9-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /var */
|
---|
| 248 | { "6A90BA39-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /home */
|
---|
| 249 | { "6A9283A5-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Alternate sector */
|
---|
| 250 |
|
---|
| 251 | { "37AFFC90-EF7D-4E96-91C3-2D7AE055B174", RTDVMVOLTYPE_IBM_GPFS },
|
---|
[86780] | 252 |
|
---|
| 253 | { "90B6FF38-B98F-4358-A21F-48F35B4A8AD3", RTDVMVOLTYPE_ARCA_OS2 }, /* OS/2 type 1 defined by Arca Noae */
|
---|
[36868] | 254 | };
|
---|
| 255 |
|
---|
[37024] | 256 | static DECLCALLBACK(int) rtDvmFmtGptProbe(PCRTDVMDISK pDisk, uint32_t *puScore)
|
---|
[36868] | 257 | {
|
---|
| 258 | int rc = VINF_SUCCESS;
|
---|
[69609] | 259 | GPTHDR Hdr;
|
---|
[36868] | 260 |
|
---|
| 261 | *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
|
---|
| 262 |
|
---|
[37024] | 263 | if (rtDvmDiskGetSectors(pDisk) >= 2)
|
---|
[36868] | 264 | {
|
---|
| 265 | /* Read from the disk and check for the signature. */
|
---|
[85877] | 266 | rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR));
|
---|
[36868] | 267 | if ( RT_SUCCESS(rc)
|
---|
| 268 | && !strncmp(&Hdr.abSignature[0], RTDVM_GPT_SIGNATURE, RT_ELEMENTS(Hdr.abSignature))
|
---|
| 269 | && RT_LE2H_U32(Hdr.u32Revision) == 0x00010000
|
---|
[69609] | 270 | && RT_LE2H_U32(Hdr.cbHeader) == sizeof(GPTHDRREV1))
|
---|
[36868] | 271 | *puScore = RTDVM_MATCH_SCORE_PERFECT;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | return rc;
|
---|
| 275 | }
|
---|
| 276 |
|
---|
[37024] | 277 | static DECLCALLBACK(int) rtDvmFmtGptOpen(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
|
---|
[36868] | 278 | {
|
---|
| 279 | int rc = VINF_SUCCESS;
|
---|
| 280 | PRTDVMFMTINTERNAL pThis = NULL;
|
---|
| 281 |
|
---|
| 282 | pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
|
---|
[40298] | 283 | if (pThis)
|
---|
[36868] | 284 | {
|
---|
| 285 | pThis->pDisk = pDisk;
|
---|
| 286 | pThis->cPartitions = 0;
|
---|
| 287 |
|
---|
| 288 | /* Read the complete GPT header and convert to host endianess. */
|
---|
[85877] | 289 | rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &pThis->HdrRev1, sizeof(pThis->HdrRev1));
|
---|
[36868] | 290 | if (RT_SUCCESS(rc))
|
---|
| 291 | {
|
---|
| 292 | pThis->HdrRev1.Hdr.u32Revision = RT_LE2H_U32(pThis->HdrRev1.Hdr.u32Revision);
|
---|
| 293 | pThis->HdrRev1.Hdr.cbHeader = RT_LE2H_U32(pThis->HdrRev1.Hdr.cbHeader);
|
---|
| 294 | pThis->HdrRev1.Hdr.u32Crc = RT_LE2H_U32(pThis->HdrRev1.Hdr.u32Crc);
|
---|
| 295 | pThis->HdrRev1.u64LbaCurrent = RT_LE2H_U64(pThis->HdrRev1.u64LbaCurrent);
|
---|
| 296 | pThis->HdrRev1.u64LbaBackup = RT_LE2H_U64(pThis->HdrRev1.u64LbaBackup);
|
---|
| 297 | pThis->HdrRev1.u64LbaFirstPartition = RT_LE2H_U64(pThis->HdrRev1.u64LbaFirstPartition);
|
---|
| 298 | pThis->HdrRev1.u64LbaLastPartition = RT_LE2H_U64(pThis->HdrRev1.u64LbaLastPartition);
|
---|
[63561] | 299 | /** @todo Disk UUID */
|
---|
[36868] | 300 | pThis->HdrRev1.u64LbaPartitionEntries = RT_LE2H_U64(pThis->HdrRev1.u64LbaPartitionEntries);
|
---|
| 301 | pThis->HdrRev1.cPartitionEntries = RT_LE2H_U32(pThis->HdrRev1.cPartitionEntries);
|
---|
| 302 | pThis->HdrRev1.cbPartitionEntry = RT_LE2H_U32(pThis->HdrRev1.cbPartitionEntry);
|
---|
| 303 | pThis->HdrRev1.u32CrcPartitionEntries = RT_LE2H_U32(pThis->HdrRev1.u32CrcPartitionEntries);
|
---|
| 304 |
|
---|
[69609] | 305 | if (pThis->HdrRev1.cbPartitionEntry == sizeof(GPTENTRY))
|
---|
[36868] | 306 | {
|
---|
[85877] | 307 | size_t cbAlignedGptEntries = RT_ALIGN_Z(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry, pDisk->cbSector);
|
---|
| 308 | pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(cbAlignedGptEntries);
|
---|
[40298] | 309 | if (pThis->paGptEntries)
|
---|
[36868] | 310 | {
|
---|
[37024] | 311 | rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(pThis->HdrRev1.u64LbaPartitionEntries, pDisk),
|
---|
[85877] | 312 | pThis->paGptEntries, cbAlignedGptEntries);
|
---|
[36868] | 313 | if (RT_SUCCESS(rc))
|
---|
| 314 | {
|
---|
| 315 | /* Count the occupied entries. */
|
---|
| 316 | for (unsigned i = 0; i < pThis->HdrRev1.cPartitionEntries; i++)
|
---|
| 317 | if (!RTUuidIsNull(&pThis->paGptEntries[i].UuidType))
|
---|
| 318 | {
|
---|
| 319 | /* Convert to host endianess. */
|
---|
[63561] | 320 | /** @todo Uuids */
|
---|
[36868] | 321 | pThis->paGptEntries[i].u64LbaFirst = RT_LE2H_U64(pThis->paGptEntries[i].u64LbaFirst);
|
---|
| 322 | pThis->paGptEntries[i].u64LbaLast = RT_LE2H_U64(pThis->paGptEntries[i].u64LbaLast);
|
---|
| 323 | pThis->paGptEntries[i].u64Flags = RT_LE2H_U64(pThis->paGptEntries[i].u64Flags);
|
---|
| 324 | for (unsigned cwc = 0; cwc < RT_ELEMENTS(pThis->paGptEntries[i].aPartitionName); cwc++)
|
---|
| 325 | pThis->paGptEntries[i].aPartitionName[cwc] = RT_LE2H_U16(pThis->paGptEntries[i].aPartitionName[cwc]);
|
---|
| 326 |
|
---|
| 327 | pThis->cPartitions++;
|
---|
| 328 | }
|
---|
[85877] | 329 |
|
---|
| 330 | if (RT_SUCCESS(rc))
|
---|
| 331 | {
|
---|
| 332 | *phVolMgrFmt = pThis;
|
---|
| 333 | return rc;
|
---|
| 334 | }
|
---|
[36868] | 335 | }
|
---|
[85877] | 336 | RTMemFree(pThis->paGptEntries);
|
---|
[36868] | 337 | }
|
---|
| 338 | else
|
---|
| 339 | rc = VERR_NO_MEMORY;
|
---|
| 340 | }
|
---|
| 341 | else
|
---|
| 342 | rc = VERR_NOT_SUPPORTED;
|
---|
| 343 | }
|
---|
[85877] | 344 | RTMemFree(pThis);
|
---|
[36868] | 345 | }
|
---|
| 346 | else
|
---|
| 347 | rc = VERR_NO_MEMORY;
|
---|
| 348 |
|
---|
| 349 | return rc;
|
---|
| 350 | }
|
---|
| 351 |
|
---|
[37024] | 352 | static DECLCALLBACK(int) rtDvmFmtGptInitialize(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
|
---|
[36868] | 353 | {
|
---|
[39083] | 354 | NOREF(pDisk); NOREF(phVolMgrFmt);
|
---|
[36868] | 355 | return VERR_NOT_IMPLEMENTED;
|
---|
| 356 | }
|
---|
| 357 |
|
---|
[37024] | 358 | static DECLCALLBACK(void) rtDvmFmtGptClose(RTDVMFMT hVolMgrFmt)
|
---|
[36868] | 359 | {
|
---|
| 360 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 361 |
|
---|
| 362 | pThis->pDisk = NULL;
|
---|
[85877] | 363 | RT_ZERO(pThis->HdrRev1);
|
---|
| 364 |
|
---|
[36868] | 365 | RTMemFree(pThis->paGptEntries);
|
---|
[85877] | 366 | pThis->paGptEntries = NULL;
|
---|
[36868] | 367 |
|
---|
| 368 | RTMemFree(pThis);
|
---|
| 369 | }
|
---|
| 370 |
|
---|
[41549] | 371 | static DECLCALLBACK(int) rtDvmFmtGptQueryRangeUse(RTDVMFMT hVolMgrFmt,
|
---|
| 372 | uint64_t off, uint64_t cbRange,
|
---|
| 373 | bool *pfUsed)
|
---|
| 374 | {
|
---|
| 375 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 376 |
|
---|
[42387] | 377 | NOREF(cbRange);
|
---|
| 378 |
|
---|
[41549] | 379 | if (off < 33*pThis->pDisk->cbSector)
|
---|
| 380 | *pfUsed = true;
|
---|
| 381 | else
|
---|
| 382 | *pfUsed = false;
|
---|
| 383 |
|
---|
| 384 | return VINF_SUCCESS;
|
---|
| 385 | }
|
---|
| 386 |
|
---|
[85877] | 387 | /** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */
|
---|
| 388 | static DECLCALLBACK(int) rtDvmFmtGptQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid)
|
---|
| 389 | {
|
---|
| 390 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 391 |
|
---|
| 392 | *pUuid = pThis->HdrRev1.DiskUuid;
|
---|
| 393 | return VINF_SUCCESS;
|
---|
| 394 | }
|
---|
| 395 |
|
---|
[37024] | 396 | static DECLCALLBACK(uint32_t) rtDvmFmtGptGetValidVolumes(RTDVMFMT hVolMgrFmt)
|
---|
[36868] | 397 | {
|
---|
| 398 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 399 |
|
---|
| 400 | return pThis->cPartitions;
|
---|
| 401 | }
|
---|
| 402 |
|
---|
[37024] | 403 | static DECLCALLBACK(uint32_t) rtDvmFmtGptGetMaxVolumes(RTDVMFMT hVolMgrFmt)
|
---|
[36868] | 404 | {
|
---|
| 405 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 406 |
|
---|
| 407 | return pThis->HdrRev1.cPartitionEntries;
|
---|
| 408 | }
|
---|
| 409 |
|
---|
| 410 | /**
|
---|
| 411 | * Creates a new volume.
|
---|
| 412 | *
|
---|
| 413 | * @returns IPRT status code.
|
---|
| 414 | * @param pThis The MBR volume manager data.
|
---|
| 415 | * @param pGptEntry The GPT entry.
|
---|
| 416 | * @param idx The index in the partition array.
|
---|
| 417 | * @param phVolFmt Where to store the volume data on success.
|
---|
| 418 | */
|
---|
[69609] | 419 | static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, PGPTENTRY pGptEntry,
|
---|
[36868] | 420 | uint32_t idx, PRTDVMVOLUMEFMT phVolFmt)
|
---|
| 421 | {
|
---|
| 422 | int rc = VINF_SUCCESS;
|
---|
| 423 | PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL));
|
---|
| 424 |
|
---|
[40298] | 425 | if (pVol)
|
---|
[36868] | 426 | {
|
---|
| 427 | pVol->pVolMgr = pThis;
|
---|
| 428 | pVol->idxEntry = idx;
|
---|
| 429 | pVol->pGptEntry = pGptEntry;
|
---|
| 430 | pVol->offStart = RTDVM_GPT_LBA2BYTE(pGptEntry->u64LbaFirst, pThis->pDisk);
|
---|
| 431 | pVol->cbVolume = RTDVM_GPT_LBA2BYTE(pGptEntry->u64LbaLast - pGptEntry->u64LbaFirst + 1, pThis->pDisk);
|
---|
| 432 |
|
---|
| 433 | *phVolFmt = pVol;
|
---|
| 434 | }
|
---|
| 435 | else
|
---|
| 436 | rc = VERR_NO_MEMORY;
|
---|
| 437 |
|
---|
| 438 | return rc;
|
---|
| 439 | }
|
---|
| 440 |
|
---|
[37024] | 441 | static DECLCALLBACK(int) rtDvmFmtGptQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt)
|
---|
[36868] | 442 | {
|
---|
| 443 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 444 |
|
---|
| 445 | if (pThis->cPartitions != 0)
|
---|
| 446 | {
|
---|
[69609] | 447 | PGPTENTRY pGptEntry = &pThis->paGptEntries[0];
|
---|
[36868] | 448 |
|
---|
| 449 | /* Search for the first non empty entry. */
|
---|
| 450 | for (unsigned i = 0; i < pThis->HdrRev1.cPartitionEntries; i++)
|
---|
| 451 | {
|
---|
| 452 | if (!RTUuidIsNull(&pGptEntry->UuidType))
|
---|
[69609] | 453 | return rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmt);
|
---|
[36868] | 454 | pGptEntry++;
|
---|
| 455 | }
|
---|
[69609] | 456 | AssertFailed();
|
---|
[36868] | 457 | }
|
---|
[69609] | 458 | return VERR_DVM_MAP_EMPTY;
|
---|
[36868] | 459 | }
|
---|
| 460 |
|
---|
[37024] | 461 | static DECLCALLBACK(int) rtDvmFmtGptQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext)
|
---|
[36868] | 462 | {
|
---|
| 463 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 464 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
[69609] | 465 | PGPTENTRY pGptEntry = pVol->pGptEntry + 1;
|
---|
[36868] | 466 |
|
---|
| 467 | for (unsigned i = pVol->idxEntry + 1; i < pThis->HdrRev1.cPartitionEntries; i++)
|
---|
| 468 | {
|
---|
| 469 | if (!RTUuidIsNull(&pGptEntry->UuidType))
|
---|
[69609] | 470 | return rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmtNext);
|
---|
[36868] | 471 | pGptEntry++;
|
---|
| 472 | }
|
---|
| 473 |
|
---|
[69609] | 474 | return VERR_DVM_MAP_NO_VOLUME;
|
---|
[36868] | 475 | }
|
---|
| 476 |
|
---|
[85894] | 477 | /** @copydoc RTDVMFMTOPS::pfnQueryTableLocations */
|
---|
| 478 | static DECLCALLBACK(int) rtDvmFmtGptQueryTableLocations(RTDVMFMT hVolMgrFmt, uint32_t fFlags, PRTDVMTABLELOCATION paLocations,
|
---|
| 479 | size_t cLocations, size_t *pcActual)
|
---|
| 480 | {
|
---|
| 481 | PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
|
---|
| 482 |
|
---|
| 483 | /*
|
---|
| 484 | * The MBR if requested.
|
---|
| 485 | */
|
---|
| 486 | int rc = VINF_SUCCESS;
|
---|
| 487 | size_t iLoc = 0;
|
---|
| 488 | if (fFlags & RTDVMMAPQTABLOC_F_INCLUDE_LEGACY)
|
---|
| 489 | {
|
---|
| 490 | if (cLocations > 0)
|
---|
| 491 | {
|
---|
| 492 | paLocations[iLoc].off = 0;
|
---|
| 493 | paLocations[iLoc].cb = RTDVM_GPT_LBA2BYTE(1, pThis->pDisk);
|
---|
| 494 | paLocations[iLoc].cbPadding = 0;
|
---|
| 495 | }
|
---|
| 496 | else
|
---|
| 497 | rc = VERR_BUFFER_OVERFLOW;
|
---|
| 498 | iLoc++;
|
---|
| 499 | }
|
---|
| 500 |
|
---|
| 501 | /*
|
---|
| 502 | * The GPT.
|
---|
| 503 | */
|
---|
| 504 | if (cLocations > iLoc)
|
---|
| 505 | {
|
---|
| 506 | uint64_t const offEnd = (pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry + pThis->pDisk->cbSector - 1)
|
---|
| 507 | / pThis->pDisk->cbSector
|
---|
| 508 | * pThis->pDisk->cbSector;
|
---|
| 509 | paLocations[iLoc].off = RTDVM_GPT_LBA2BYTE(1, pThis->pDisk);
|
---|
| 510 | paLocations[iLoc].cb = offEnd - paLocations[iLoc].off;
|
---|
| 511 |
|
---|
| 512 | uint64_t uLbaFirstPart = pThis->pDisk->cbDisk / pThis->pDisk->cbSector;
|
---|
| 513 | for (unsigned i = 0; i < pThis->HdrRev1.cPartitionEntries; i++)
|
---|
| 514 | if ( pThis->paGptEntries[i].u64LbaFirst < uLbaFirstPart
|
---|
| 515 | && !RTUuidIsNull(&pThis->paGptEntries[i].UuidType))
|
---|
| 516 | uLbaFirstPart = pThis->paGptEntries[i].u64LbaFirst;
|
---|
| 517 |
|
---|
| 518 | paLocations[iLoc].cbPadding = RTDVM_GPT_LBA2BYTE(uLbaFirstPart, pThis->pDisk);
|
---|
| 519 | if (paLocations[iLoc].cbPadding > offEnd)
|
---|
| 520 | paLocations[iLoc].cbPadding -= offEnd;
|
---|
| 521 | else
|
---|
| 522 | AssertFailedStmt(paLocations[iLoc].cbPadding = 0);
|
---|
| 523 | }
|
---|
| 524 | else
|
---|
| 525 | rc = VERR_BUFFER_OVERFLOW;
|
---|
| 526 | iLoc++;
|
---|
| 527 |
|
---|
| 528 | /*
|
---|
| 529 | * Return values.
|
---|
| 530 | */
|
---|
| 531 | if (pcActual)
|
---|
| 532 | *pcActual = iLoc;
|
---|
| 533 | else if (cLocations != iLoc && RT_SUCCESS(rc))
|
---|
| 534 | {
|
---|
| 535 | RT_BZERO(&paLocations[iLoc], (cLocations - iLoc) * sizeof(paLocations[0]));
|
---|
| 536 | rc = VERR_BUFFER_UNDERFLOW;
|
---|
| 537 | }
|
---|
| 538 | return rc;
|
---|
| 539 | }
|
---|
| 540 |
|
---|
[37024] | 541 | static DECLCALLBACK(void) rtDvmFmtGptVolumeClose(RTDVMVOLUMEFMT hVolFmt)
|
---|
[36868] | 542 | {
|
---|
| 543 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 544 |
|
---|
| 545 | pVol->pVolMgr = NULL;
|
---|
| 546 | pVol->offStart = 0;
|
---|
| 547 | pVol->cbVolume = 0;
|
---|
| 548 | pVol->pGptEntry = NULL;
|
---|
| 549 |
|
---|
| 550 | RTMemFree(pVol);
|
---|
| 551 | }
|
---|
| 552 |
|
---|
[37024] | 553 | static DECLCALLBACK(uint64_t) rtDvmFmtGptVolumeGetSize(RTDVMVOLUMEFMT hVolFmt)
|
---|
[36868] | 554 | {
|
---|
| 555 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 556 |
|
---|
| 557 | return pVol->cbVolume;
|
---|
| 558 | }
|
---|
| 559 |
|
---|
[37024] | 560 | static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryName(RTDVMVOLUMEFMT hVolFmt, char **ppszVolName)
|
---|
[36868] | 561 | {
|
---|
| 562 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 563 |
|
---|
| 564 | *ppszVolName = NULL;
|
---|
[69609] | 565 | return RTUtf16ToUtf8Ex(&pVol->pGptEntry->aPartitionName[0], RT_ELEMENTS(pVol->pGptEntry->aPartitionName),
|
---|
| 566 | ppszVolName, 0, NULL);
|
---|
[36868] | 567 | }
|
---|
| 568 |
|
---|
[37024] | 569 | static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtGptVolumeGetType(RTDVMVOLUMEFMT hVolFmt)
|
---|
[36868] | 570 | {
|
---|
| 571 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 572 |
|
---|
| 573 | for (unsigned i = 0; i < RT_ELEMENTS(g_aPartType2DvmVolTypes); i++)
|
---|
| 574 | if (!RTUuidCompareStr(&pVol->pGptEntry->UuidType, g_aPartType2DvmVolTypes[i].pcszUuid))
|
---|
[69609] | 575 | return g_aPartType2DvmVolTypes[i].enmVolType;
|
---|
[36868] | 576 |
|
---|
[69609] | 577 | return RTDVMVOLTYPE_UNKNOWN;
|
---|
[36868] | 578 | }
|
---|
| 579 |
|
---|
[37024] | 580 | static DECLCALLBACK(uint64_t) rtDvmFmtGptVolumeGetFlags(RTDVMVOLUMEFMT hVolFmt)
|
---|
[36868] | 581 | {
|
---|
[77256] | 582 | NOREF(hVolFmt);
|
---|
| 583 | return DVMVOLUME_F_CONTIGUOUS;
|
---|
[36868] | 584 | }
|
---|
| 585 |
|
---|
[77970] | 586 | static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryRange(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast)
|
---|
[77256] | 587 | {
|
---|
| 588 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 589 | *poffStart = pVol->offStart;
|
---|
[77970] | 590 | *poffLast = pVol->offStart + pVol->cbVolume - 1;
|
---|
[77256] | 591 | return VINF_SUCCESS;
|
---|
| 592 | }
|
---|
| 593 |
|
---|
[57444] | 594 | static DECLCALLBACK(bool) rtDvmFmtGptVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt,
|
---|
| 595 | uint64_t offStart, size_t cbRange,
|
---|
| 596 | uint64_t *poffVol,
|
---|
| 597 | uint64_t *pcbIntersect)
|
---|
[40027] | 598 | {
|
---|
| 599 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 600 |
|
---|
| 601 | if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart))
|
---|
| 602 | {
|
---|
| 603 | *poffVol = offStart - pVol->offStart;
|
---|
| 604 | *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart);
|
---|
[69609] | 605 | return true;
|
---|
[40027] | 606 | }
|
---|
[69609] | 607 | return false;
|
---|
[40027] | 608 | }
|
---|
| 609 |
|
---|
[85877] | 610 | /** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
|
---|
| 611 | static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
|
---|
| 612 | {
|
---|
| 613 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 614 | PRTDVMFMTINTERNAL pVolMgr = pVol->pVolMgr;
|
---|
| 615 | *poffTable = RTDVM_GPT_LBA2BYTE(1, pVolMgr->pDisk);
|
---|
| 616 | *pcbTable = RTDVM_GPT_LBA2BYTE(pVolMgr->HdrRev1.u64LbaPartitionEntries, pVolMgr->pDisk)
|
---|
| 617 | + RT_ALIGN_Z(pVolMgr->HdrRev1.cPartitionEntries * pVolMgr->HdrRev1.cbPartitionEntry, pVolMgr->pDisk->cbSector)
|
---|
| 618 | - *poffTable;
|
---|
| 619 | return VINF_SUCCESS;
|
---|
| 620 | }
|
---|
| 621 |
|
---|
| 622 | /** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
|
---|
| 623 | static DECLCALLBACK(uint32_t) rtDvmFmtGptVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
|
---|
| 624 | {
|
---|
| 625 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 626 | switch (enmIndex)
|
---|
| 627 | {
|
---|
| 628 | case RTDVMVOLIDX_USER_VISIBLE:
|
---|
| 629 | case RTDVMVOLIDX_ALL:
|
---|
| 630 | case RTDVMVOLIDX_LINUX:
|
---|
| 631 | return pVol->idxEntry + 1;
|
---|
| 632 |
|
---|
| 633 | case RTDVMVOLIDX_IN_TABLE:
|
---|
| 634 | return pVol->idxEntry;
|
---|
| 635 |
|
---|
| 636 | case RTDVMVOLIDX_INVALID:
|
---|
[85887] | 637 | case RTDVMVOLIDX_HOST:
|
---|
[85877] | 638 | case RTDVMVOLIDX_END:
|
---|
[85887] | 639 | case RTDVMVOLIDX_32BIT_HACK:
|
---|
[85877] | 640 | break;
|
---|
| 641 | /* no default! */
|
---|
| 642 | }
|
---|
| 643 | AssertFailed();
|
---|
| 644 | return UINT32_MAX;
|
---|
| 645 | }
|
---|
| 646 |
|
---|
| 647 | /** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
|
---|
| 648 | static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
|
---|
| 649 | void *pvBuf, size_t cbBuf, size_t *pcbBuf)
|
---|
| 650 | {
|
---|
| 651 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 652 | switch (enmProperty)
|
---|
| 653 | {
|
---|
| 654 | case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
|
---|
| 655 | case RTDVMVOLPROP_MBR_FIRST_HEAD:
|
---|
| 656 | case RTDVMVOLPROP_MBR_FIRST_SECTOR:
|
---|
| 657 | case RTDVMVOLPROP_MBR_LAST_CYLINDER:
|
---|
| 658 | case RTDVMVOLPROP_MBR_LAST_HEAD:
|
---|
| 659 | case RTDVMVOLPROP_MBR_LAST_SECTOR:
|
---|
| 660 | case RTDVMVOLPROP_MBR_TYPE:
|
---|
| 661 | return VERR_NOT_SUPPORTED;
|
---|
| 662 |
|
---|
| 663 | case RTDVMVOLPROP_GPT_TYPE:
|
---|
| 664 | *pcbBuf = sizeof(RTUUID);
|
---|
| 665 | Assert(cbBuf >= *pcbBuf);
|
---|
| 666 | *(PRTUUID)pvBuf = pVol->pGptEntry->UuidType;
|
---|
| 667 | return VINF_SUCCESS;
|
---|
| 668 |
|
---|
| 669 | case RTDVMVOLPROP_GPT_UUID:
|
---|
| 670 | *pcbBuf = sizeof(RTUUID);
|
---|
| 671 | Assert(cbBuf >= *pcbBuf);
|
---|
| 672 | *(PRTUUID)pvBuf = pVol->pGptEntry->UuidPartition;
|
---|
| 673 | return VINF_SUCCESS;
|
---|
| 674 |
|
---|
| 675 | case RTDVMVOLPROP_INVALID:
|
---|
| 676 | case RTDVMVOLPROP_END:
|
---|
| 677 | case RTDVMVOLPROP_32BIT_HACK:
|
---|
| 678 | break;
|
---|
| 679 | /* not default! */
|
---|
| 680 | }
|
---|
| 681 | AssertFailed();
|
---|
| 682 | RT_NOREF(cbBuf);
|
---|
| 683 | return VERR_NOT_SUPPORTED;
|
---|
| 684 | }
|
---|
| 685 |
|
---|
[37024] | 686 | static DECLCALLBACK(int) rtDvmFmtGptVolumeRead(RTDVMVOLUMEFMT hVolFmt, uint64_t off, void *pvBuf, size_t cbRead)
|
---|
[36868] | 687 | {
|
---|
| 688 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 689 | AssertReturn(off + cbRead <= pVol->cbVolume, VERR_INVALID_PARAMETER);
|
---|
| 690 |
|
---|
[99989] | 691 | return rtDvmDiskReadUnaligned(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbRead);
|
---|
[36868] | 692 | }
|
---|
| 693 |
|
---|
[37024] | 694 | static DECLCALLBACK(int) rtDvmFmtGptVolumeWrite(RTDVMVOLUMEFMT hVolFmt, uint64_t off, const void *pvBuf, size_t cbWrite)
|
---|
[36868] | 695 | {
|
---|
| 696 | PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
|
---|
| 697 | AssertReturn(off + cbWrite <= pVol->cbVolume, VERR_INVALID_PARAMETER);
|
---|
| 698 |
|
---|
[37024] | 699 | return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbWrite);
|
---|
[36868] | 700 | }
|
---|
| 701 |
|
---|
[85124] | 702 | DECL_HIDDEN_CONST(const RTDVMFMTOPS) g_rtDvmFmtGpt =
|
---|
[36868] | 703 | {
|
---|
[69616] | 704 | /* pszFmt */
|
---|
[36868] | 705 | "GPT",
|
---|
[69616] | 706 | /* enmFormat, */
|
---|
| 707 | RTDVMFORMATTYPE_GPT,
|
---|
[36868] | 708 | /* pfnProbe */
|
---|
[37024] | 709 | rtDvmFmtGptProbe,
|
---|
[36868] | 710 | /* pfnOpen */
|
---|
[37024] | 711 | rtDvmFmtGptOpen,
|
---|
[36868] | 712 | /* pfnInitialize */
|
---|
[37024] | 713 | rtDvmFmtGptInitialize,
|
---|
[36868] | 714 | /* pfnClose */
|
---|
[37024] | 715 | rtDvmFmtGptClose,
|
---|
[41549] | 716 | /* pfnQueryRangeUse */
|
---|
| 717 | rtDvmFmtGptQueryRangeUse,
|
---|
[85877] | 718 | /* pfnQueryDiskUuid */
|
---|
| 719 | rtDvmFmtGptQueryDiskUuid,
|
---|
[36868] | 720 | /* pfnGetValidVolumes */
|
---|
[37024] | 721 | rtDvmFmtGptGetValidVolumes,
|
---|
[36868] | 722 | /* pfnGetMaxVolumes */
|
---|
[37024] | 723 | rtDvmFmtGptGetMaxVolumes,
|
---|
[36868] | 724 | /* pfnQueryFirstVolume */
|
---|
[37024] | 725 | rtDvmFmtGptQueryFirstVolume,
|
---|
[36868] | 726 | /* pfnQueryNextVolume */
|
---|
[37024] | 727 | rtDvmFmtGptQueryNextVolume,
|
---|
[85894] | 728 | /* pfnQueryTableLocations */
|
---|
| 729 | rtDvmFmtGptQueryTableLocations,
|
---|
[36868] | 730 | /* pfnVolumeClose */
|
---|
[37024] | 731 | rtDvmFmtGptVolumeClose,
|
---|
[36868] | 732 | /* pfnVolumeGetSize */
|
---|
[37024] | 733 | rtDvmFmtGptVolumeGetSize,
|
---|
[36868] | 734 | /* pfnVolumeQueryName */
|
---|
[37024] | 735 | rtDvmFmtGptVolumeQueryName,
|
---|
[36868] | 736 | /* pfnVolumeGetType */
|
---|
[37024] | 737 | rtDvmFmtGptVolumeGetType,
|
---|
[36868] | 738 | /* pfnVolumeGetFlags */
|
---|
[37024] | 739 | rtDvmFmtGptVolumeGetFlags,
|
---|
[77256] | 740 | /* pfnVolumeQueryRange */
|
---|
| 741 | rtDvmFmtGptVolumeQueryRange,
|
---|
[40027] | 742 | /* pfnVolumeIsRangeIntersecting */
|
---|
| 743 | rtDvmFmtGptVolumeIsRangeIntersecting,
|
---|
[85877] | 744 | /* pfnVolumeQueryTableLocation */
|
---|
| 745 | rtDvmFmtGptVolumeQueryTableLocation,
|
---|
| 746 | /* pfnVolumeGetIndex */
|
---|
| 747 | rtDvmFmtGptVolumeGetIndex,
|
---|
| 748 | /* pfnVolumeQueryProp */
|
---|
| 749 | rtDvmFmtGptVolumeQueryProp,
|
---|
[36868] | 750 | /* pfnVolumeRead */
|
---|
[37024] | 751 | rtDvmFmtGptVolumeRead,
|
---|
[36868] | 752 | /* pfnVolumeWrite */
|
---|
[37024] | 753 | rtDvmFmtGptVolumeWrite
|
---|
[36868] | 754 | };
|
---|
| 755 |
|
---|