1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#ifndef BLOCK_VHDX_H
19#define BLOCK_VHDX_H
20
21#define KiB (1 * 1024)
22#define MiB (KiB * 1024)
23#define GiB (MiB * 1024)
24#define TiB ((uint64_t) GiB * 1024)
25
26#define DEFAULT_LOG_SIZE 1048576
27
28
29
30
31
32
33
34
35
36
37
38
39#define VHDX_HEADER_BLOCK_SIZE (64 * 1024)
40
41#define VHDX_FILE_ID_OFFSET 0
42#define VHDX_HEADER1_OFFSET (VHDX_HEADER_BLOCK_SIZE * 1)
43#define VHDX_HEADER2_OFFSET (VHDX_HEADER_BLOCK_SIZE * 2)
44#define VHDX_REGION_TABLE_OFFSET (VHDX_HEADER_BLOCK_SIZE * 3)
45#define VHDX_REGION_TABLE2_OFFSET (VHDX_HEADER_BLOCK_SIZE * 4)
46
47#define VHDX_HEADER_SECTION_END (1 * MiB)
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL
66typedef struct VHDXFileIdentifier {
67 uint64_t signature;
68 uint16_t creator[256];
69
70
71} VHDXFileIdentifier;
72
73
74
75
76
77
78typedef struct QEMU_PACKED MSGUID {
79 uint32_t data1;
80 uint16_t data2;
81 uint16_t data3;
82 uint8_t data4[8];
83} MSGUID;
84
85#define guid_eq(a, b) \
86 (memcmp(&(a), &(b), sizeof(MSGUID)) == 0)
87
88#define VHDX_HEADER_SIZE (4 * 1024)
89
90
91
92
93
94
95
96#define VHDX_HEADER_SIGNATURE 0x64616568
97typedef struct QEMU_PACKED VHDXHeader {
98 uint32_t signature;
99 uint32_t checksum;
100 uint64_t sequence_number;
101
102
103
104 MSGUID file_write_guid;
105
106
107
108 MSGUID data_write_guid;
109
110
111
112
113
114
115
116
117
118
119
120
121
122 MSGUID log_guid;
123
124
125
126 uint16_t log_version;
127
128 uint16_t version;
129
130 uint32_t log_length;
131
132 uint64_t log_offset;
133
134} VHDXHeader;
135
136
137#define VHDX_REGION_SIGNATURE 0x69676572
138typedef struct QEMU_PACKED VHDXRegionTableHeader {
139 uint32_t signature;
140 uint32_t checksum;
141 uint32_t entry_count;
142 uint32_t reserved;
143} VHDXRegionTableHeader;
144
145
146
147
148
149
150
151#define VHDX_REGION_ENTRY_REQUIRED 0x01
152
153
154typedef struct QEMU_PACKED VHDXRegionTableEntry {
155 MSGUID guid;
156 uint64_t file_offset;
157
158 uint32_t length;
159 uint32_t data_bits;
160} VHDXRegionTableEntry;
161
162
163
164#define VHDX_LOG_MIN_SIZE (1024 * 1024)
165#define VHDX_LOG_SECTOR_SIZE 4096
166#define VHDX_LOG_HDR_SIZE 64
167#define VHDX_LOG_SIGNATURE 0x65676f6c
168typedef struct QEMU_PACKED VHDXLogEntryHeader {
169 uint32_t signature;
170 uint32_t checksum;
171 uint32_t entry_length;
172 uint32_t tail;
173
174
175 uint64_t sequence_number;
176
177 uint32_t descriptor_count;
178
179 uint32_t reserved;
180 MSGUID log_guid;
181
182
183 uint64_t flushed_file_offset;
184
185 uint64_t last_file_offset;
186
187} VHDXLogEntryHeader;
188
189#define VHDX_LOG_DESC_SIZE 32
190#define VHDX_LOG_DESC_SIGNATURE 0x63736564
191#define VHDX_LOG_ZERO_SIGNATURE 0x6f72657a
192typedef struct QEMU_PACKED VHDXLogDescriptor {
193 uint32_t signature;
194 union {
195 uint32_t reserved;
196 uint32_t trailing_bytes;
197
198 };
199 union {
200 uint64_t zero_length;
201
202 uint64_t leading_bytes;
203
204 };
205 uint64_t file_offset;
206
207 uint64_t sequence_number;
208
209} VHDXLogDescriptor;
210
211#define VHDX_LOG_DATA_SIGNATURE 0x61746164
212typedef struct QEMU_PACKED VHDXLogDataSector {
213 uint32_t data_signature;
214 uint32_t sequence_high;
215 uint8_t data[4084];
216
217
218 uint32_t sequence_low;
219} VHDXLogDataSector;
220
221
222
223
224
225
226#define PAYLOAD_BLOCK_NOT_PRESENT 0
227#define PAYLOAD_BLOCK_UNDEFINED 1
228#define PAYLOAD_BLOCK_ZERO 2
229#define PAYLOAD_BLOCK_UNMAPPED 3
230#define PAYLOAD_BLOCK_UNMAPPED_v095 5
231#define PAYLOAD_BLOCK_FULLY_PRESENT 6
232#define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7
233
234#define SB_BLOCK_NOT_PRESENT 0
235#define SB_BLOCK_PRESENT 6
236
237
238#define VHDX_MAX_SECTORS_PER_BLOCK (1 << 23)
239
240
241
242#define VHDX_BAT_STATE_BIT_MASK 0x07
243#define VHDX_BAT_FILE_OFF_MASK 0xFFFFFFFFFFF00000ULL
244typedef uint64_t VHDXBatEntry;
245
246
247
248#define VHDX_METADATA_ENTRY_SIZE 32
249#define VHDX_METADATA_MAX_ENTRIES 2047
250#define VHDX_METADATA_TABLE_MAX_SIZE \
251 (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
252#define VHDX_METADATA_SIGNATURE 0x617461646174656DULL
253typedef struct QEMU_PACKED VHDXMetadataTableHeader {
254 uint64_t signature;
255 uint16_t reserved;
256 uint16_t entry_count;
257 uint32_t reserved2[5];
258} VHDXMetadataTableHeader;
259
260#define VHDX_META_FLAGS_IS_USER 0x01
261#define VHDX_META_FLAGS_IS_VIRTUAL_DISK 0x02
262
263#define VHDX_META_FLAGS_IS_REQUIRED 0x04
264
265typedef struct QEMU_PACKED VHDXMetadataTableEntry {
266 MSGUID item_id;
267 uint32_t offset;
268
269
270
271 uint32_t length;
272 uint32_t data_bits;
273
274 uint32_t reserved2;
275} VHDXMetadataTableEntry;
276
277#define VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED 0x01
278
279
280
281#define VHDX_PARAMS_HAS_PARENT 0x02
282#define VHDX_BLOCK_SIZE_MIN (1 * MiB)
283#define VHDX_BLOCK_SIZE_MAX (256 * MiB)
284typedef struct QEMU_PACKED VHDXFileParameters {
285 uint32_t block_size;
286
287 uint32_t data_bits;
288
289} VHDXFileParameters;
290
291#define VHDX_MAX_IMAGE_SIZE ((uint64_t) 64 * TiB)
292typedef struct QEMU_PACKED VHDXVirtualDiskSize {
293 uint64_t virtual_disk_size;
294
295
296} VHDXVirtualDiskSize;
297
298typedef struct QEMU_PACKED VHDXPage83Data {
299 MSGUID page_83_data;
300
301} VHDXPage83Data;
302
303typedef struct QEMU_PACKED VHDXVirtualDiskLogicalSectorSize {
304 uint32_t logical_sector_size;
305
306} VHDXVirtualDiskLogicalSectorSize;
307
308typedef struct QEMU_PACKED VHDXVirtualDiskPhysicalSectorSize {
309 uint32_t physical_sector_size;
310
311} VHDXVirtualDiskPhysicalSectorSize;
312
313typedef struct QEMU_PACKED VHDXParentLocatorHeader {
314 MSGUID locator_type;
315 uint16_t reserved;
316 uint16_t key_value_count;
317
318} VHDXParentLocatorHeader;
319
320
321typedef struct QEMU_PACKED VHDXParentLocatorEntry {
322 uint32_t key_offset;
323 uint32_t value_offset;
324 uint16_t key_length;
325 uint16_t value_length;
326} VHDXParentLocatorEntry;
327
328
329
330
331typedef struct VHDXMetadataEntries {
332 VHDXMetadataTableEntry file_parameters_entry;
333 VHDXMetadataTableEntry virtual_disk_size_entry;
334 VHDXMetadataTableEntry page83_data_entry;
335 VHDXMetadataTableEntry logical_sector_size_entry;
336 VHDXMetadataTableEntry phys_sector_size_entry;
337 VHDXMetadataTableEntry parent_locator_entry;
338 uint16_t present;
339} VHDXMetadataEntries;
340
341typedef struct VHDXLogEntries {
342 uint64_t offset;
343 uint64_t length;
344 uint32_t write;
345 uint32_t read;
346 VHDXLogEntryHeader *hdr;
347 void *desc_buffer;
348 uint64_t sequence;
349 uint32_t tail;
350} VHDXLogEntries;
351
352typedef struct VHDXRegionEntry {
353 uint64_t start;
354 uint64_t end;
355 QLIST_ENTRY(VHDXRegionEntry) entries;
356} VHDXRegionEntry;
357
358typedef struct BDRVVHDXState {
359 CoMutex lock;
360
361 int curr_header;
362 VHDXHeader *headers[2];
363
364 VHDXRegionTableHeader rt;
365 VHDXRegionTableEntry bat_rt;
366 VHDXRegionTableEntry metadata_rt;
367
368 VHDXMetadataTableHeader metadata_hdr;
369 VHDXMetadataEntries metadata_entries;
370
371 VHDXFileParameters params;
372 uint32_t block_size;
373 uint32_t block_size_bits;
374 uint32_t sectors_per_block;
375 uint32_t sectors_per_block_bits;
376
377 uint64_t virtual_disk_size;
378 uint32_t logical_sector_size;
379 uint32_t physical_sector_size;
380
381 uint64_t chunk_ratio;
382 uint32_t chunk_ratio_bits;
383 uint32_t logical_sector_size_bits;
384
385 uint32_t bat_entries;
386 VHDXBatEntry *bat;
387 uint64_t bat_offset;
388
389 bool first_visible_write;
390 MSGUID session_guid;
391
392 VHDXLogEntries log;
393
394 VHDXParentLocatorHeader parent_header;
395 VHDXParentLocatorEntry *parent_entries;
396
397 Error *migration_blocker;
398
399 bool log_replayed_on_open;
400
401 QLIST_HEAD(VHDXRegionHead, VHDXRegionEntry) regions;
402} BDRVVHDXState;
403
404void vhdx_guid_generate(MSGUID *guid);
405
406int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s, bool rw,
407 MSGUID *log_guid);
408
409uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset);
410uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
411 int crc_offset);
412
413bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
414
415int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
416 Error **errp);
417
418int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
419 void *data, uint32_t length, uint64_t offset);
420
421static inline void leguid_to_cpus(MSGUID *guid)
422{
423 le32_to_cpus(&guid->data1);
424 le16_to_cpus(&guid->data2);
425 le16_to_cpus(&guid->data3);
426}
427
428static inline void cpu_to_leguids(MSGUID *guid)
429{
430 cpu_to_le32s(&guid->data1);
431 cpu_to_le16s(&guid->data2);
432 cpu_to_le16s(&guid->data3);
433}
434
435void vhdx_header_le_import(VHDXHeader *h);
436void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h);
437void vhdx_log_desc_le_import(VHDXLogDescriptor *d);
438void vhdx_log_desc_le_export(VHDXLogDescriptor *d);
439void vhdx_log_data_le_import(VHDXLogDataSector *d);
440void vhdx_log_data_le_export(VHDXLogDataSector *d);
441void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr);
442void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr);
443void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr);
444void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr);
445void vhdx_region_entry_le_import(VHDXRegionTableEntry *e);
446void vhdx_region_entry_le_export(VHDXRegionTableEntry *e);
447void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr);
448void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr);
449void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e);
450void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e);
451int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s);
452
453#endif
454