qemu/block/vhdx.h
<<
>>
Prefs
   1/*
   2 * Block driver for Hyper-V VHDX Images
   3 *
   4 * Copyright (c) 2013 Red Hat, Inc.,
   5 *
   6 * Authors:
   7 *  Jeff Cody <jcody@redhat.com>
   8 *
   9 *  This is based on the "VHDX Format Specification v0.95", published 4/12/2012
  10 *  by Microsoft:
  11 *      https://www.microsoft.com/en-us/download/details.aspx?id=29681
  12 *
  13 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  14 * See the COPYING.LIB file in the top-level directory.
  15 *
  16 */
  17
  18#ifndef BLOCK_VHDX_H
  19#define BLOCK_VHDX_H
  20
  21/* Structures and fields present in the VHDX file */
  22
  23/* The header section has the following blocks,
  24 * each block is 64KB:
  25 *
  26 * _____________________________________________________________________________
  27 * | File Id. |   Header 1    | Header 2   | Region Table |  Reserved (768KB)  |
  28 * |----------|---------------|------------|--------------|--------------------|
  29 * |          |               |            |              |                    |
  30 * 0.........64KB...........128KB........192KB..........256KB................1MB
  31 */
  32
  33#define VHDX_HEADER_BLOCK_SIZE      (64*1024)
  34
  35#define VHDX_FILE_ID_OFFSET         0
  36#define VHDX_HEADER1_OFFSET         (VHDX_HEADER_BLOCK_SIZE*1)
  37#define VHDX_HEADER2_OFFSET         (VHDX_HEADER_BLOCK_SIZE*2)
  38#define VHDX_REGION_TABLE_OFFSET    (VHDX_HEADER_BLOCK_SIZE*3)
  39
  40
  41/*
  42 * A note on the use of MS-GUID fields.  For more details on the GUID,
  43 * please see: https://en.wikipedia.org/wiki/Globally_unique_identifier.
  44 *
  45 * The VHDX specification only states that these are MS GUIDs, and which
  46 * bytes are data1-data4. It makes no mention of what algorithm should be used
  47 * to generate the GUID, nor what standard.  However, looking at the specified
  48 * known GUID fields, it appears the GUIDs are:
  49 *  Standard/DCE GUID type  (noted by 10b in the MSB of byte 0 of .data4)
  50 *  Random algorithm        (noted by 0x4XXX for .data3)
  51 */
  52
  53/* ---- HEADER SECTION STRUCTURES ---- */
  54
  55/* These structures are ones that are defined in the VHDX specification
  56 * document */
  57
  58typedef struct VHDXFileIdentifier {
  59    uint64_t    signature;              /* "vhdxfile" in ASCII */
  60    uint16_t    creator[256];           /* optional; utf-16 string to identify
  61                                           the vhdx file creator.  Diagnotistic
  62                                           only */
  63} VHDXFileIdentifier;
  64
  65
  66/* the guid is a 16 byte unique ID - the definition for this used by
  67 * Microsoft is not just 16 bytes though - it is a structure that is defined,
  68 * so we need to follow it here so that endianness does not trip us up */
  69
  70typedef struct MSGUID {
  71    uint32_t  data1;
  72    uint16_t  data2;
  73    uint16_t  data3;
  74    uint8_t   data4[8];
  75} MSGUID;
  76
  77#define guid_eq(a, b) \
  78    (memcmp(&(a), &(b), sizeof(MSGUID)) == 0)
  79
  80#define VHDX_HEADER_SIZE (4*1024)   /* although the vhdx_header struct in disk
  81                                       is only 582 bytes, for purposes of crc
  82                                       the header is the first 4KB of the 64KB
  83                                       block */
  84
  85/* The full header is 4KB, although the actual header data is much smaller.
  86 * But for the checksum calculation, it is over the entire 4KB structure,
  87 * not just the defined portion of it */
  88typedef struct QEMU_PACKED VHDXHeader {
  89    uint32_t    signature;              /* "head" in ASCII */
  90    uint32_t    checksum;               /* CRC-32C hash of the whole header */
  91    uint64_t    sequence_number;        /* Seq number of this header.  Each
  92                                           VHDX file has 2 of these headers,
  93                                           and only the header with the highest
  94                                           sequence number is valid */
  95    MSGUID      file_write_guid;       /* 128 bit unique identifier. Must be
  96                                           updated to new, unique value before
  97                                           the first modification is made to
  98                                           file */
  99    MSGUID      data_write_guid;        /* 128 bit unique identifier. Must be
 100                                           updated to new, unique value before
 101                                           the first modification is made to
 102                                           visible data.   Visbile data is
 103                                           defined as:
 104                                                    - system & user metadata
 105                                                    - raw block data
 106                                                    - disk size
 107                                                    - any change that will
 108                                                      cause the virtual disk
 109                                                      sector read to differ
 110
 111                                           This does not need to change if
 112                                           blocks are re-arranged */
 113    MSGUID      log_guid;               /* 128 bit unique identifier. If zero,
 114                                           there is no valid log. If non-zero,
 115                                           log entries with this guid are
 116                                           valid. */
 117    uint16_t    log_version;            /* version of the log format. Mustn't be
 118                                           zero, unless log_guid is also zero */
 119    uint16_t    version;                /* version of th evhdx file.  Currently,
 120                                           only supported version is "1" */
 121    uint32_t    log_length;             /* length of the log.  Must be multiple
 122                                           of 1MB */
 123    uint64_t    log_offset;             /* byte offset in the file of the log.
 124                                           Must also be a multiple of 1MB */
 125} VHDXHeader;
 126
 127/* Header for the region table block */
 128typedef struct QEMU_PACKED VHDXRegionTableHeader {
 129    uint32_t    signature;              /* "regi" in ASCII */
 130    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
 131    uint32_t    entry_count;            /* number of valid entries */
 132    uint32_t    reserved;
 133} VHDXRegionTableHeader;
 134
 135/* Individual region table entry.  There may be a maximum of 2047 of these
 136 *
 137 *  There are two known region table properties.  Both are required.
 138 *  BAT (block allocation table):  2DC27766F62342009D64115E9BFD4A08
 139 *  Metadata:                      8B7CA20647904B9AB8FE575F050F886E
 140 */
 141#define VHDX_REGION_ENTRY_REQUIRED  0x01    /* if set, parser must understand
 142                                               this entry in order to open
 143                                               file */
 144typedef struct QEMU_PACKED VHDXRegionTableEntry {
 145    MSGUID      guid;                   /* 128-bit unique identifier */
 146    uint64_t    file_offset;            /* offset of the object in the file.
 147                                           Must be multiple of 1MB */
 148    uint32_t    length;                 /* length, in bytes, of the object */
 149    uint32_t    data_bits;
 150} VHDXRegionTableEntry;
 151
 152
 153/* ---- LOG ENTRY STRUCTURES ---- */
 154#define VHDX_LOG_HDR_SIZE 64
 155typedef struct QEMU_PACKED VHDXLogEntryHeader {
 156    uint32_t    signature;              /* "loge" in ASCII */
 157    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
 158    uint32_t    entry_length;           /* length in bytes, multiple of 1MB */
 159    uint32_t    tail;                   /* byte offset of first log entry of a
 160                                           seq, where this entry is the last
 161                                           entry */
 162    uint64_t    sequence_number;        /* incremented with each log entry.
 163                                           May not be zero. */
 164    uint32_t    descriptor_count;       /* number of descriptors in this log
 165                                           entry, must be >= 0 */
 166    uint32_t    reserved;
 167    MSGUID      log_guid;               /* value of the log_guid from
 168                                           vhdx_header.  If not found in
 169                                           vhdx_header, it is invalid */
 170    uint64_t    flushed_file_offset;    /* see spec for full details - this
 171                                           sould be vhdx file size in bytes */
 172    uint64_t    last_file_offset;       /* size in bytes that all allocated
 173                                           file structures fit into */
 174} VHDXLogEntryHeader;
 175
 176#define VHDX_LOG_DESC_SIZE 32
 177
 178typedef struct QEMU_PACKED VHDXLogDescriptor {
 179    uint32_t    signature;              /* "zero" or "desc" in ASCII */
 180    union  {
 181        uint32_t    reserved;           /* zero desc */
 182        uint32_t    trailing_bytes;     /* data desc: bytes 4092-4096 of the
 183                                           data sector */
 184    };
 185    union {
 186        uint64_t    zero_length;        /* zero desc: length of the section to
 187                                           zero */
 188        uint64_t    leading_bytes;      /* data desc: bytes 0-7 of the data
 189                                           sector */
 190    };
 191    uint64_t    file_offset;            /* file offset to write zeros - multiple
 192                                           of 4kB */
 193    uint64_t    sequence_number;        /* must match same field in
 194                                           vhdx_log_entry_header */
 195} VHDXLogDescriptor;
 196
 197typedef struct QEMU_PACKED VHDXLogDataSector {
 198    uint32_t    data_signature;         /* "data" in ASCII */
 199    uint32_t    sequence_high;          /* 4 MSB of 8 byte sequence_number */
 200    uint8_t     data[4084];             /* raw data, bytes 8-4091 (inclusive).
 201                                           see the data descriptor field for the
 202                                           other mising bytes */
 203    uint32_t    sequence_low;           /* 4 LSB of 8 byte sequence_number */
 204} VHDXLogDataSector;
 205
 206
 207
 208/* block states - different state values depending on whether it is a
 209 * payload block, or a sector block. */
 210
 211#define PAYLOAD_BLOCK_NOT_PRESENT       0
 212#define PAYLOAD_BLOCK_UNDEFINED         1
 213#define PAYLOAD_BLOCK_ZERO              2
 214#define PAYLOAD_BLOCK_UNMAPPED          5
 215#define PAYLOAD_BLOCK_FULL_PRESENT      6
 216#define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7
 217
 218#define SB_BLOCK_NOT_PRESENT    0
 219#define SB_BLOCK_PRESENT        6
 220
 221/* per the spec */
 222#define VHDX_MAX_SECTORS_PER_BLOCK  (1<<23)
 223
 224/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
 225   other bits are reserved */
 226#define VHDX_BAT_STATE_BIT_MASK 0x07
 227#define VHDX_BAT_FILE_OFF_BITS (64-44)
 228typedef uint64_t VHDXBatEntry;
 229
 230/* ---- METADATA REGION STRUCTURES ---- */
 231
 232#define VHDX_METADATA_ENTRY_SIZE 32
 233#define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */
 234#define VHDX_METADATA_TABLE_MAX_SIZE \
 235    (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
 236typedef struct QEMU_PACKED VHDXMetadataTableHeader {
 237    uint64_t    signature;              /* "metadata" in ASCII */
 238    uint16_t    reserved;
 239    uint16_t    entry_count;            /* number table entries. <= 2047 */
 240    uint32_t    reserved2[5];
 241} VHDXMetadataTableHeader;
 242
 243#define VHDX_META_FLAGS_IS_USER         0x01    /* max 1024 entries */
 244#define VHDX_META_FLAGS_IS_VIRTUAL_DISK 0x02    /* virtual disk metadata if set,
 245                                                   otherwise file metdata */
 246#define VHDX_META_FLAGS_IS_REQUIRED     0x04    /* parse must understand this
 247                                                   entry to open the file */
 248typedef struct QEMU_PACKED VHDXMetadataTableEntry {
 249    MSGUID      item_id;                /* 128-bit identifier for metadata */
 250    uint32_t    offset;                 /* byte offset of the metadata.  At
 251                                           least 64kB.  Relative to start of
 252                                           metadata region */
 253                                        /* note: if length = 0, so is offset */
 254    uint32_t    length;                 /* length of metadata. <= 1MB. */
 255    uint32_t    data_bits;      /* least-significant 3 bits are flags, the
 256                                   rest are reserved (see above) */
 257    uint32_t    reserved2;
 258} VHDXMetadataTableEntry;
 259
 260#define VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED 0x01   /* Do not change any blocks to
 261                                                   be BLOCK_NOT_PRESENT.
 262                                                   If set indicates a fixed
 263                                                   size VHDX file */
 264#define VHDX_PARAMS_HAS_PARENT           0x02    /* has parent / backing file */
 265typedef struct QEMU_PACKED VHDXFileParameters {
 266    uint32_t    block_size;             /* size of each payload block, always
 267                                           power of 2, <= 256MB and >= 1MB. */
 268    uint32_t data_bits;     /* least-significant 2 bits are flags, the rest
 269                               are reserved (see above) */
 270} VHDXFileParameters;
 271
 272typedef struct QEMU_PACKED VHDXVirtualDiskSize {
 273    uint64_t    virtual_disk_size;      /* Size of the virtual disk, in bytes.
 274                                           Must be multiple of the sector size,
 275                                           max of 64TB */
 276} VHDXVirtualDiskSize;
 277
 278typedef struct QEMU_PACKED VHDXPage83Data {
 279    MSGUID      page_83_data[16];       /* unique id for scsi devices that
 280                                           support page 0x83 */
 281} VHDXPage83Data;
 282
 283typedef struct QEMU_PACKED VHDXVirtualDiskLogicalSectorSize {
 284    uint32_t    logical_sector_size;    /* virtual disk sector size (in bytes).
 285                                           Can only be 512 or 4096 bytes */
 286} VHDXVirtualDiskLogicalSectorSize;
 287
 288typedef struct QEMU_PACKED VHDXVirtualDiskPhysicalSectorSize {
 289    uint32_t    physical_sector_size;   /* physical sector size (in bytes).
 290                                           Can only be 512 or 4096 bytes */
 291} VHDXVirtualDiskPhysicalSectorSize;
 292
 293typedef struct QEMU_PACKED VHDXParentLocatorHeader {
 294    MSGUID      locator_type[16];       /* type of the parent virtual disk. */
 295    uint16_t    reserved;
 296    uint16_t    key_value_count;        /* number of key/value pairs for this
 297                                           locator */
 298} VHDXParentLocatorHeader;
 299
 300/* key and value strings are UNICODE strings, UTF-16 LE encoding, no NULs */
 301typedef struct QEMU_PACKED VHDXParentLocatorEntry {
 302    uint32_t    key_offset;             /* offset in metadata for key, > 0 */
 303    uint32_t    value_offset;           /* offset in metadata for value, >0 */
 304    uint16_t    key_length;             /* length of entry key, > 0 */
 305    uint16_t    value_length;           /* length of entry value, > 0 */
 306} VHDXParentLocatorEntry;
 307
 308
 309/* ----- END VHDX SPECIFICATION STRUCTURES ---- */
 310
 311
 312uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
 313                            int crc_offset);
 314
 315bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
 316
 317
 318static void leguid_to_cpus(MSGUID *guid)
 319{
 320    le32_to_cpus(&guid->data1);
 321    le16_to_cpus(&guid->data2);
 322    le16_to_cpus(&guid->data3);
 323}
 324
 325#endif
 326