Statistics
| Branch: | Revision:

root / block / vhdx.h @ cc84d90f

History | View | Annotate | Download (14.8 kB)

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

    
58
typedef 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

    
70
typedef 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 */
88
typedef 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 */
128
typedef 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 */
144
typedef 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
155
typedef 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
                                           should 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

    
178
typedef 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

    
197
typedef 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)
228
typedef 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))
236
typedef 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 */
248
typedef 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 */
265
typedef 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

    
272
typedef 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

    
278
typedef struct QEMU_PACKED VHDXPage83Data {
279
    MSGUID      page_83_data[16];       /* unique id for scsi devices that
280
                                           support page 0x83 */
281
} VHDXPage83Data;
282

    
283
typedef 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

    
288
typedef 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

    
293
typedef 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 */
301
typedef 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

    
312
uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
313
                            int crc_offset);
314

    
315
bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
316

    
317

    
318
static 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