Statistics
| Branch: | Revision:

root / block / vhdx.h @ 69152c09

History | View | Annotate | Download (19.1 kB)

1 203cdba3 Jeff Cody
/*
2 203cdba3 Jeff Cody
 * Block driver for Hyper-V VHDX Images
3 203cdba3 Jeff Cody
 *
4 203cdba3 Jeff Cody
 * Copyright (c) 2013 Red Hat, Inc.,
5 203cdba3 Jeff Cody
 *
6 203cdba3 Jeff Cody
 * Authors:
7 203cdba3 Jeff Cody
 *  Jeff Cody <jcody@redhat.com>
8 203cdba3 Jeff Cody
 *
9 6e9d290b Jeff Cody
 *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
10 203cdba3 Jeff Cody
 *  by Microsoft:
11 6e9d290b Jeff Cody
 *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
12 203cdba3 Jeff Cody
 *
13 203cdba3 Jeff Cody
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
14 203cdba3 Jeff Cody
 * See the COPYING.LIB file in the top-level directory.
15 203cdba3 Jeff Cody
 *
16 203cdba3 Jeff Cody
 */
17 203cdba3 Jeff Cody
18 203cdba3 Jeff Cody
#ifndef BLOCK_VHDX_H
19 203cdba3 Jeff Cody
#define BLOCK_VHDX_H
20 203cdba3 Jeff Cody
21 3412f7b1 Jeff Cody
#define KiB              (1 * 1024)
22 3412f7b1 Jeff Cody
#define MiB            (KiB * 1024)
23 3412f7b1 Jeff Cody
#define GiB            (MiB * 1024)
24 3412f7b1 Jeff Cody
#define TiB ((uint64_t) GiB * 1024)
25 3412f7b1 Jeff Cody
26 203cdba3 Jeff Cody
/* Structures and fields present in the VHDX file */
27 203cdba3 Jeff Cody
28 203cdba3 Jeff Cody
/* The header section has the following blocks,
29 203cdba3 Jeff Cody
 * each block is 64KB:
30 203cdba3 Jeff Cody
 *
31 203cdba3 Jeff Cody
 * _____________________________________________________________________________
32 203cdba3 Jeff Cody
 * | File Id. |   Header 1    | Header 2   | Region Table |  Reserved (768KB)  |
33 203cdba3 Jeff Cody
 * |----------|---------------|------------|--------------|--------------------|
34 203cdba3 Jeff Cody
 * |          |               |            |              |                    |
35 203cdba3 Jeff Cody
 * 0.........64KB...........128KB........192KB..........256KB................1MB
36 203cdba3 Jeff Cody
 */
37 203cdba3 Jeff Cody
38 625565d2 Jeff Cody
#define VHDX_HEADER_BLOCK_SIZE      (64 * 1024)
39 203cdba3 Jeff Cody
40 203cdba3 Jeff Cody
#define VHDX_FILE_ID_OFFSET         0
41 625565d2 Jeff Cody
#define VHDX_HEADER1_OFFSET         (VHDX_HEADER_BLOCK_SIZE * 1)
42 625565d2 Jeff Cody
#define VHDX_HEADER2_OFFSET         (VHDX_HEADER_BLOCK_SIZE * 2)
43 625565d2 Jeff Cody
#define VHDX_REGION_TABLE_OFFSET    (VHDX_HEADER_BLOCK_SIZE * 3)
44 3412f7b1 Jeff Cody
#define VHDX_REGION_TABLE2_OFFSET   (VHDX_HEADER_BLOCK_SIZE * 4)
45 203cdba3 Jeff Cody
46 3412f7b1 Jeff Cody
#define VHDX_HEADER_SECTION_END     (1 * MiB)
47 203cdba3 Jeff Cody
/*
48 203cdba3 Jeff Cody
 * A note on the use of MS-GUID fields.  For more details on the GUID,
49 203cdba3 Jeff Cody
 * please see: https://en.wikipedia.org/wiki/Globally_unique_identifier.
50 203cdba3 Jeff Cody
 *
51 203cdba3 Jeff Cody
 * The VHDX specification only states that these are MS GUIDs, and which
52 203cdba3 Jeff Cody
 * bytes are data1-data4. It makes no mention of what algorithm should be used
53 203cdba3 Jeff Cody
 * to generate the GUID, nor what standard.  However, looking at the specified
54 203cdba3 Jeff Cody
 * known GUID fields, it appears the GUIDs are:
55 203cdba3 Jeff Cody
 *  Standard/DCE GUID type  (noted by 10b in the MSB of byte 0 of .data4)
56 203cdba3 Jeff Cody
 *  Random algorithm        (noted by 0x4XXX for .data3)
57 203cdba3 Jeff Cody
 */
58 203cdba3 Jeff Cody
59 203cdba3 Jeff Cody
/* ---- HEADER SECTION STRUCTURES ---- */
60 203cdba3 Jeff Cody
61 203cdba3 Jeff Cody
/* These structures are ones that are defined in the VHDX specification
62 203cdba3 Jeff Cody
 * document */
63 203cdba3 Jeff Cody
64 3412f7b1 Jeff Cody
#define VHDX_FILE_SIGNATURE 0x656C696678646876  /* "vhdxfile" in ASCII */
65 203cdba3 Jeff Cody
typedef struct VHDXFileIdentifier {
66 203cdba3 Jeff Cody
    uint64_t    signature;              /* "vhdxfile" in ASCII */
67 203cdba3 Jeff Cody
    uint16_t    creator[256];           /* optional; utf-16 string to identify
68 61c02e56 Jeff Cody
                                           the vhdx file creator.  Diagnostic
69 203cdba3 Jeff Cody
                                           only */
70 203cdba3 Jeff Cody
} VHDXFileIdentifier;
71 203cdba3 Jeff Cody
72 203cdba3 Jeff Cody
73 203cdba3 Jeff Cody
/* the guid is a 16 byte unique ID - the definition for this used by
74 203cdba3 Jeff Cody
 * Microsoft is not just 16 bytes though - it is a structure that is defined,
75 203cdba3 Jeff Cody
 * so we need to follow it here so that endianness does not trip us up */
76 203cdba3 Jeff Cody
77 4f18b782 Jeff Cody
typedef struct QEMU_PACKED MSGUID {
78 203cdba3 Jeff Cody
    uint32_t  data1;
79 203cdba3 Jeff Cody
    uint16_t  data2;
80 203cdba3 Jeff Cody
    uint16_t  data3;
81 203cdba3 Jeff Cody
    uint8_t   data4[8];
82 203cdba3 Jeff Cody
} MSGUID;
83 203cdba3 Jeff Cody
84 203cdba3 Jeff Cody
#define guid_eq(a, b) \
85 203cdba3 Jeff Cody
    (memcmp(&(a), &(b), sizeof(MSGUID)) == 0)
86 203cdba3 Jeff Cody
87 625565d2 Jeff Cody
#define VHDX_HEADER_SIZE (4 * 1024)   /* although the vhdx_header struct in disk
88 625565d2 Jeff Cody
                                         is only 582 bytes, for purposes of crc
89 625565d2 Jeff Cody
                                         the header is the first 4KB of the 64KB
90 625565d2 Jeff Cody
                                         block */
91 203cdba3 Jeff Cody
92 203cdba3 Jeff Cody
/* The full header is 4KB, although the actual header data is much smaller.
93 203cdba3 Jeff Cody
 * But for the checksum calculation, it is over the entire 4KB structure,
94 203cdba3 Jeff Cody
 * not just the defined portion of it */
95 3412f7b1 Jeff Cody
#define VHDX_HEADER_SIGNATURE 0x64616568
96 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXHeader {
97 203cdba3 Jeff Cody
    uint32_t    signature;              /* "head" in ASCII */
98 203cdba3 Jeff Cody
    uint32_t    checksum;               /* CRC-32C hash of the whole header */
99 203cdba3 Jeff Cody
    uint64_t    sequence_number;        /* Seq number of this header.  Each
100 203cdba3 Jeff Cody
                                           VHDX file has 2 of these headers,
101 203cdba3 Jeff Cody
                                           and only the header with the highest
102 203cdba3 Jeff Cody
                                           sequence number is valid */
103 625565d2 Jeff Cody
    MSGUID      file_write_guid;        /* 128 bit unique identifier. Must be
104 203cdba3 Jeff Cody
                                           updated to new, unique value before
105 203cdba3 Jeff Cody
                                           the first modification is made to
106 203cdba3 Jeff Cody
                                           file */
107 203cdba3 Jeff Cody
    MSGUID      data_write_guid;        /* 128 bit unique identifier. Must be
108 203cdba3 Jeff Cody
                                           updated to new, unique value before
109 203cdba3 Jeff Cody
                                           the first modification is made to
110 203cdba3 Jeff Cody
                                           visible data.   Visbile data is
111 203cdba3 Jeff Cody
                                           defined as:
112 203cdba3 Jeff Cody
                                                    - system & user metadata
113 203cdba3 Jeff Cody
                                                    - raw block data
114 203cdba3 Jeff Cody
                                                    - disk size
115 203cdba3 Jeff Cody
                                                    - any change that will
116 203cdba3 Jeff Cody
                                                      cause the virtual disk
117 203cdba3 Jeff Cody
                                                      sector read to differ
118 203cdba3 Jeff Cody

119 203cdba3 Jeff Cody
                                           This does not need to change if
120 203cdba3 Jeff Cody
                                           blocks are re-arranged */
121 203cdba3 Jeff Cody
    MSGUID      log_guid;               /* 128 bit unique identifier. If zero,
122 203cdba3 Jeff Cody
                                           there is no valid log. If non-zero,
123 203cdba3 Jeff Cody
                                           log entries with this guid are
124 203cdba3 Jeff Cody
                                           valid. */
125 61c02e56 Jeff Cody
    uint16_t    log_version;            /* version of the log format. Must be
126 61c02e56 Jeff Cody
                                           set to zero */
127 6e9d290b Jeff Cody
    uint16_t    version;                /* version of the vhdx file.  Currently,
128 203cdba3 Jeff Cody
                                           only supported version is "1" */
129 203cdba3 Jeff Cody
    uint32_t    log_length;             /* length of the log.  Must be multiple
130 203cdba3 Jeff Cody
                                           of 1MB */
131 203cdba3 Jeff Cody
    uint64_t    log_offset;             /* byte offset in the file of the log.
132 203cdba3 Jeff Cody
                                           Must also be a multiple of 1MB */
133 203cdba3 Jeff Cody
} VHDXHeader;
134 203cdba3 Jeff Cody
135 203cdba3 Jeff Cody
/* Header for the region table block */
136 3412f7b1 Jeff Cody
#define VHDX_REGION_SIGNATURE  0x69676572  /* "regi" in ASCII */
137 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXRegionTableHeader {
138 203cdba3 Jeff Cody
    uint32_t    signature;              /* "regi" in ASCII */
139 203cdba3 Jeff Cody
    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
140 203cdba3 Jeff Cody
    uint32_t    entry_count;            /* number of valid entries */
141 203cdba3 Jeff Cody
    uint32_t    reserved;
142 203cdba3 Jeff Cody
} VHDXRegionTableHeader;
143 203cdba3 Jeff Cody
144 203cdba3 Jeff Cody
/* Individual region table entry.  There may be a maximum of 2047 of these
145 203cdba3 Jeff Cody
 *
146 203cdba3 Jeff Cody
 *  There are two known region table properties.  Both are required.
147 203cdba3 Jeff Cody
 *  BAT (block allocation table):  2DC27766F62342009D64115E9BFD4A08
148 203cdba3 Jeff Cody
 *  Metadata:                      8B7CA20647904B9AB8FE575F050F886E
149 203cdba3 Jeff Cody
 */
150 203cdba3 Jeff Cody
#define VHDX_REGION_ENTRY_REQUIRED  0x01    /* if set, parser must understand
151 203cdba3 Jeff Cody
                                               this entry in order to open
152 203cdba3 Jeff Cody
                                               file */
153 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXRegionTableEntry {
154 203cdba3 Jeff Cody
    MSGUID      guid;                   /* 128-bit unique identifier */
155 203cdba3 Jeff Cody
    uint64_t    file_offset;            /* offset of the object in the file.
156 203cdba3 Jeff Cody
                                           Must be multiple of 1MB */
157 203cdba3 Jeff Cody
    uint32_t    length;                 /* length, in bytes, of the object */
158 203cdba3 Jeff Cody
    uint32_t    data_bits;
159 203cdba3 Jeff Cody
} VHDXRegionTableEntry;
160 203cdba3 Jeff Cody
161 203cdba3 Jeff Cody
162 203cdba3 Jeff Cody
/* ---- LOG ENTRY STRUCTURES ---- */
163 625565d2 Jeff Cody
#define VHDX_LOG_MIN_SIZE (1024 * 1024)
164 625565d2 Jeff Cody
#define VHDX_LOG_SECTOR_SIZE 4096
165 203cdba3 Jeff Cody
#define VHDX_LOG_HDR_SIZE 64
166 625565d2 Jeff Cody
#define VHDX_LOG_SIGNATURE 0x65676f6c
167 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXLogEntryHeader {
168 203cdba3 Jeff Cody
    uint32_t    signature;              /* "loge" in ASCII */
169 203cdba3 Jeff Cody
    uint32_t    checksum;               /* CRC-32C hash of the 64KB table */
170 203cdba3 Jeff Cody
    uint32_t    entry_length;           /* length in bytes, multiple of 1MB */
171 203cdba3 Jeff Cody
    uint32_t    tail;                   /* byte offset of first log entry of a
172 203cdba3 Jeff Cody
                                           seq, where this entry is the last
173 203cdba3 Jeff Cody
                                           entry */
174 203cdba3 Jeff Cody
    uint64_t    sequence_number;        /* incremented with each log entry.
175 203cdba3 Jeff Cody
                                           May not be zero. */
176 203cdba3 Jeff Cody
    uint32_t    descriptor_count;       /* number of descriptors in this log
177 203cdba3 Jeff Cody
                                           entry, must be >= 0 */
178 203cdba3 Jeff Cody
    uint32_t    reserved;
179 203cdba3 Jeff Cody
    MSGUID      log_guid;               /* value of the log_guid from
180 203cdba3 Jeff Cody
                                           vhdx_header.  If not found in
181 203cdba3 Jeff Cody
                                           vhdx_header, it is invalid */
182 203cdba3 Jeff Cody
    uint64_t    flushed_file_offset;    /* see spec for full details - this
183 52f35022 Stefan Weil
                                           should be vhdx file size in bytes */
184 203cdba3 Jeff Cody
    uint64_t    last_file_offset;       /* size in bytes that all allocated
185 203cdba3 Jeff Cody
                                           file structures fit into */
186 203cdba3 Jeff Cody
} VHDXLogEntryHeader;
187 203cdba3 Jeff Cody
188 203cdba3 Jeff Cody
#define VHDX_LOG_DESC_SIZE 32
189 625565d2 Jeff Cody
#define VHDX_LOG_DESC_SIGNATURE 0x63736564
190 625565d2 Jeff Cody
#define VHDX_LOG_ZERO_SIGNATURE 0x6f72657a
191 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXLogDescriptor {
192 203cdba3 Jeff Cody
    uint32_t    signature;              /* "zero" or "desc" in ASCII */
193 203cdba3 Jeff Cody
    union  {
194 203cdba3 Jeff Cody
        uint32_t    reserved;           /* zero desc */
195 203cdba3 Jeff Cody
        uint32_t    trailing_bytes;     /* data desc: bytes 4092-4096 of the
196 203cdba3 Jeff Cody
                                           data sector */
197 203cdba3 Jeff Cody
    };
198 203cdba3 Jeff Cody
    union {
199 203cdba3 Jeff Cody
        uint64_t    zero_length;        /* zero desc: length of the section to
200 203cdba3 Jeff Cody
                                           zero */
201 203cdba3 Jeff Cody
        uint64_t    leading_bytes;      /* data desc: bytes 0-7 of the data
202 203cdba3 Jeff Cody
                                           sector */
203 203cdba3 Jeff Cody
    };
204 203cdba3 Jeff Cody
    uint64_t    file_offset;            /* file offset to write zeros - multiple
205 203cdba3 Jeff Cody
                                           of 4kB */
206 203cdba3 Jeff Cody
    uint64_t    sequence_number;        /* must match same field in
207 203cdba3 Jeff Cody
                                           vhdx_log_entry_header */
208 203cdba3 Jeff Cody
} VHDXLogDescriptor;
209 203cdba3 Jeff Cody
210 625565d2 Jeff Cody
#define VHDX_LOG_DATA_SIGNATURE 0x61746164
211 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXLogDataSector {
212 203cdba3 Jeff Cody
    uint32_t    data_signature;         /* "data" in ASCII */
213 203cdba3 Jeff Cody
    uint32_t    sequence_high;          /* 4 MSB of 8 byte sequence_number */
214 203cdba3 Jeff Cody
    uint8_t     data[4084];             /* raw data, bytes 8-4091 (inclusive).
215 203cdba3 Jeff Cody
                                           see the data descriptor field for the
216 203cdba3 Jeff Cody
                                           other mising bytes */
217 203cdba3 Jeff Cody
    uint32_t    sequence_low;           /* 4 LSB of 8 byte sequence_number */
218 203cdba3 Jeff Cody
} VHDXLogDataSector;
219 203cdba3 Jeff Cody
220 203cdba3 Jeff Cody
221 203cdba3 Jeff Cody
222 203cdba3 Jeff Cody
/* block states - different state values depending on whether it is a
223 203cdba3 Jeff Cody
 * payload block, or a sector block. */
224 203cdba3 Jeff Cody
225 203cdba3 Jeff Cody
#define PAYLOAD_BLOCK_NOT_PRESENT       0
226 203cdba3 Jeff Cody
#define PAYLOAD_BLOCK_UNDEFINED         1
227 203cdba3 Jeff Cody
#define PAYLOAD_BLOCK_ZERO              2
228 203cdba3 Jeff Cody
#define PAYLOAD_BLOCK_UNMAPPED          5
229 d92aa883 Jeff Cody
#define PAYLOAD_BLOCK_FULLY_PRESENT     6
230 203cdba3 Jeff Cody
#define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7
231 203cdba3 Jeff Cody
232 203cdba3 Jeff Cody
#define SB_BLOCK_NOT_PRESENT    0
233 203cdba3 Jeff Cody
#define SB_BLOCK_PRESENT        6
234 203cdba3 Jeff Cody
235 203cdba3 Jeff Cody
/* per the spec */
236 625565d2 Jeff Cody
#define VHDX_MAX_SECTORS_PER_BLOCK  (1 << 23)
237 203cdba3 Jeff Cody
238 203cdba3 Jeff Cody
/* upper 44 bits are the file offset in 1MB units lower 3 bits are the state
239 203cdba3 Jeff Cody
   other bits are reserved */
240 203cdba3 Jeff Cody
#define VHDX_BAT_STATE_BIT_MASK 0x07
241 1a848fd4 Jeff Cody
#define VHDX_BAT_FILE_OFF_MASK  0xFFFFFFFFFFF00000 /* upper 44 bits */
242 203cdba3 Jeff Cody
typedef uint64_t VHDXBatEntry;
243 203cdba3 Jeff Cody
244 203cdba3 Jeff Cody
/* ---- METADATA REGION STRUCTURES ---- */
245 203cdba3 Jeff Cody
246 203cdba3 Jeff Cody
#define VHDX_METADATA_ENTRY_SIZE 32
247 203cdba3 Jeff Cody
#define VHDX_METADATA_MAX_ENTRIES 2047  /* not including the header */
248 203cdba3 Jeff Cody
#define VHDX_METADATA_TABLE_MAX_SIZE \
249 203cdba3 Jeff Cody
    (VHDX_METADATA_ENTRY_SIZE * (VHDX_METADATA_MAX_ENTRIES+1))
250 3412f7b1 Jeff Cody
#define VHDX_METADATA_SIGNATURE 0x617461646174656D  /* "metadata" in ASCII */
251 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXMetadataTableHeader {
252 203cdba3 Jeff Cody
    uint64_t    signature;              /* "metadata" in ASCII */
253 203cdba3 Jeff Cody
    uint16_t    reserved;
254 203cdba3 Jeff Cody
    uint16_t    entry_count;            /* number table entries. <= 2047 */
255 203cdba3 Jeff Cody
    uint32_t    reserved2[5];
256 203cdba3 Jeff Cody
} VHDXMetadataTableHeader;
257 203cdba3 Jeff Cody
258 203cdba3 Jeff Cody
#define VHDX_META_FLAGS_IS_USER         0x01    /* max 1024 entries */
259 203cdba3 Jeff Cody
#define VHDX_META_FLAGS_IS_VIRTUAL_DISK 0x02    /* virtual disk metadata if set,
260 203cdba3 Jeff Cody
                                                   otherwise file metdata */
261 203cdba3 Jeff Cody
#define VHDX_META_FLAGS_IS_REQUIRED     0x04    /* parse must understand this
262 203cdba3 Jeff Cody
                                                   entry to open the file */
263 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXMetadataTableEntry {
264 203cdba3 Jeff Cody
    MSGUID      item_id;                /* 128-bit identifier for metadata */
265 203cdba3 Jeff Cody
    uint32_t    offset;                 /* byte offset of the metadata.  At
266 203cdba3 Jeff Cody
                                           least 64kB.  Relative to start of
267 203cdba3 Jeff Cody
                                           metadata region */
268 203cdba3 Jeff Cody
                                        /* note: if length = 0, so is offset */
269 203cdba3 Jeff Cody
    uint32_t    length;                 /* length of metadata. <= 1MB. */
270 625565d2 Jeff Cody
    uint32_t    data_bits;              /* least-significant 3 bits are flags,
271 625565d2 Jeff Cody
                                           the rest are reserved (see above) */
272 203cdba3 Jeff Cody
    uint32_t    reserved2;
273 203cdba3 Jeff Cody
} VHDXMetadataTableEntry;
274 203cdba3 Jeff Cody
275 203cdba3 Jeff Cody
#define VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED 0x01   /* Do not change any blocks to
276 203cdba3 Jeff Cody
                                                   be BLOCK_NOT_PRESENT.
277 203cdba3 Jeff Cody
                                                   If set indicates a fixed
278 203cdba3 Jeff Cody
                                                   size VHDX file */
279 203cdba3 Jeff Cody
#define VHDX_PARAMS_HAS_PARENT           0x02    /* has parent / backing file */
280 3412f7b1 Jeff Cody
#define VHDX_BLOCK_SIZE_MIN             (1   * MiB)
281 3412f7b1 Jeff Cody
#define VHDX_BLOCK_SIZE_MAX             (256 * MiB)
282 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXFileParameters {
283 203cdba3 Jeff Cody
    uint32_t    block_size;             /* size of each payload block, always
284 203cdba3 Jeff Cody
                                           power of 2, <= 256MB and >= 1MB. */
285 625565d2 Jeff Cody
    uint32_t data_bits;                 /* least-significant 2 bits are flags,
286 625565d2 Jeff Cody
                                           the rest are reserved (see above) */
287 203cdba3 Jeff Cody
} VHDXFileParameters;
288 203cdba3 Jeff Cody
289 3412f7b1 Jeff Cody
#define VHDX_MAX_IMAGE_SIZE  ((uint64_t) 64 * TiB)
290 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXVirtualDiskSize {
291 203cdba3 Jeff Cody
    uint64_t    virtual_disk_size;      /* Size of the virtual disk, in bytes.
292 203cdba3 Jeff Cody
                                           Must be multiple of the sector size,
293 203cdba3 Jeff Cody
                                           max of 64TB */
294 203cdba3 Jeff Cody
} VHDXVirtualDiskSize;
295 203cdba3 Jeff Cody
296 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXPage83Data {
297 61c02e56 Jeff Cody
    MSGUID      page_83_data;           /* unique id for scsi devices that
298 203cdba3 Jeff Cody
                                           support page 0x83 */
299 203cdba3 Jeff Cody
} VHDXPage83Data;
300 203cdba3 Jeff Cody
301 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXVirtualDiskLogicalSectorSize {
302 203cdba3 Jeff Cody
    uint32_t    logical_sector_size;    /* virtual disk sector size (in bytes).
303 203cdba3 Jeff Cody
                                           Can only be 512 or 4096 bytes */
304 203cdba3 Jeff Cody
} VHDXVirtualDiskLogicalSectorSize;
305 203cdba3 Jeff Cody
306 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXVirtualDiskPhysicalSectorSize {
307 203cdba3 Jeff Cody
    uint32_t    physical_sector_size;   /* physical sector size (in bytes).
308 203cdba3 Jeff Cody
                                           Can only be 512 or 4096 bytes */
309 203cdba3 Jeff Cody
} VHDXVirtualDiskPhysicalSectorSize;
310 203cdba3 Jeff Cody
311 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXParentLocatorHeader {
312 61c02e56 Jeff Cody
    MSGUID      locator_type;           /* type of the parent virtual disk. */
313 203cdba3 Jeff Cody
    uint16_t    reserved;
314 203cdba3 Jeff Cody
    uint16_t    key_value_count;        /* number of key/value pairs for this
315 203cdba3 Jeff Cody
                                           locator */
316 203cdba3 Jeff Cody
} VHDXParentLocatorHeader;
317 203cdba3 Jeff Cody
318 203cdba3 Jeff Cody
/* key and value strings are UNICODE strings, UTF-16 LE encoding, no NULs */
319 203cdba3 Jeff Cody
typedef struct QEMU_PACKED VHDXParentLocatorEntry {
320 203cdba3 Jeff Cody
    uint32_t    key_offset;             /* offset in metadata for key, > 0 */
321 203cdba3 Jeff Cody
    uint32_t    value_offset;           /* offset in metadata for value, >0 */
322 203cdba3 Jeff Cody
    uint16_t    key_length;             /* length of entry key, > 0 */
323 203cdba3 Jeff Cody
    uint16_t    value_length;           /* length of entry value, > 0 */
324 203cdba3 Jeff Cody
} VHDXParentLocatorEntry;
325 203cdba3 Jeff Cody
326 203cdba3 Jeff Cody
327 203cdba3 Jeff Cody
/* ----- END VHDX SPECIFICATION STRUCTURES ---- */
328 203cdba3 Jeff Cody
329 28541d46 Jeff Cody
typedef struct VHDXMetadataEntries {
330 28541d46 Jeff Cody
    VHDXMetadataTableEntry file_parameters_entry;
331 28541d46 Jeff Cody
    VHDXMetadataTableEntry virtual_disk_size_entry;
332 28541d46 Jeff Cody
    VHDXMetadataTableEntry page83_data_entry;
333 28541d46 Jeff Cody
    VHDXMetadataTableEntry logical_sector_size_entry;
334 28541d46 Jeff Cody
    VHDXMetadataTableEntry phys_sector_size_entry;
335 28541d46 Jeff Cody
    VHDXMetadataTableEntry parent_locator_entry;
336 28541d46 Jeff Cody
    uint16_t present;
337 28541d46 Jeff Cody
} VHDXMetadataEntries;
338 28541d46 Jeff Cody
339 625565d2 Jeff Cody
typedef struct VHDXLogEntries {
340 625565d2 Jeff Cody
    uint64_t offset;
341 625565d2 Jeff Cody
    uint64_t length;
342 0a43a1b5 Jeff Cody
    uint32_t write;
343 0a43a1b5 Jeff Cody
    uint32_t read;
344 0a43a1b5 Jeff Cody
    VHDXLogEntryHeader *hdr;
345 0a43a1b5 Jeff Cody
    void *desc_buffer;
346 0a43a1b5 Jeff Cody
    uint64_t sequence;
347 625565d2 Jeff Cody
    uint32_t tail;
348 625565d2 Jeff Cody
} VHDXLogEntries;
349 625565d2 Jeff Cody
350 1a848fd4 Jeff Cody
typedef struct VHDXRegionEntry {
351 1a848fd4 Jeff Cody
    uint64_t start;
352 1a848fd4 Jeff Cody
    uint64_t end;
353 1a848fd4 Jeff Cody
    QLIST_ENTRY(VHDXRegionEntry) entries;
354 1a848fd4 Jeff Cody
} VHDXRegionEntry;
355 1a848fd4 Jeff Cody
356 28541d46 Jeff Cody
typedef struct BDRVVHDXState {
357 28541d46 Jeff Cody
    CoMutex lock;
358 28541d46 Jeff Cody
359 28541d46 Jeff Cody
    int curr_header;
360 28541d46 Jeff Cody
    VHDXHeader *headers[2];
361 28541d46 Jeff Cody
362 28541d46 Jeff Cody
    VHDXRegionTableHeader rt;
363 28541d46 Jeff Cody
    VHDXRegionTableEntry bat_rt;         /* region table for the BAT */
364 28541d46 Jeff Cody
    VHDXRegionTableEntry metadata_rt;    /* region table for the metadata */
365 28541d46 Jeff Cody
366 28541d46 Jeff Cody
    VHDXMetadataTableHeader metadata_hdr;
367 28541d46 Jeff Cody
    VHDXMetadataEntries metadata_entries;
368 28541d46 Jeff Cody
369 28541d46 Jeff Cody
    VHDXFileParameters params;
370 28541d46 Jeff Cody
    uint32_t block_size;
371 28541d46 Jeff Cody
    uint32_t block_size_bits;
372 28541d46 Jeff Cody
    uint32_t sectors_per_block;
373 28541d46 Jeff Cody
    uint32_t sectors_per_block_bits;
374 28541d46 Jeff Cody
375 28541d46 Jeff Cody
    uint64_t virtual_disk_size;
376 28541d46 Jeff Cody
    uint32_t logical_sector_size;
377 28541d46 Jeff Cody
    uint32_t physical_sector_size;
378 28541d46 Jeff Cody
379 28541d46 Jeff Cody
    uint64_t chunk_ratio;
380 28541d46 Jeff Cody
    uint32_t chunk_ratio_bits;
381 28541d46 Jeff Cody
    uint32_t logical_sector_size_bits;
382 28541d46 Jeff Cody
383 28541d46 Jeff Cody
    uint32_t bat_entries;
384 28541d46 Jeff Cody
    VHDXBatEntry *bat;
385 28541d46 Jeff Cody
    uint64_t bat_offset;
386 28541d46 Jeff Cody
387 c3906c5e Jeff Cody
    bool first_visible_write;
388 28541d46 Jeff Cody
    MSGUID session_guid;
389 28541d46 Jeff Cody
390 625565d2 Jeff Cody
    VHDXLogEntries log;
391 625565d2 Jeff Cody
392 28541d46 Jeff Cody
    VHDXParentLocatorHeader parent_header;
393 28541d46 Jeff Cody
    VHDXParentLocatorEntry *parent_entries;
394 28541d46 Jeff Cody
395 28541d46 Jeff Cody
    Error *migration_blocker;
396 1a848fd4 Jeff Cody
397 1a848fd4 Jeff Cody
    QLIST_HEAD(VHDXRegionHead, VHDXRegionEntry) regions;
398 28541d46 Jeff Cody
} BDRVVHDXState;
399 e8d4e5ff Jeff Cody
400 4f18b782 Jeff Cody
void vhdx_guid_generate(MSGUID *guid);
401 4f18b782 Jeff Cody
402 c3906c5e Jeff Cody
int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s, bool rw,
403 c3906c5e Jeff Cody
                        MSGUID *log_guid);
404 c3906c5e Jeff Cody
405 4f18b782 Jeff Cody
uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset);
406 e8d4e5ff Jeff Cody
uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size,
407 e8d4e5ff Jeff Cody
                            int crc_offset);
408 e8d4e5ff Jeff Cody
409 e8d4e5ff Jeff Cody
bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset);
410 e8d4e5ff Jeff Cody
411 0a43a1b5 Jeff Cody
int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed);
412 e8d4e5ff Jeff Cody
413 8adc5233 Jeff Cody
int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
414 8adc5233 Jeff Cody
                             void *data, uint32_t length, uint64_t offset);
415 8adc5233 Jeff Cody
416 4f18b782 Jeff Cody
static inline void leguid_to_cpus(MSGUID *guid)
417 e8d4e5ff Jeff Cody
{
418 e8d4e5ff Jeff Cody
    le32_to_cpus(&guid->data1);
419 e8d4e5ff Jeff Cody
    le16_to_cpus(&guid->data2);
420 e8d4e5ff Jeff Cody
    le16_to_cpus(&guid->data3);
421 e8d4e5ff Jeff Cody
}
422 e8d4e5ff Jeff Cody
423 4f18b782 Jeff Cody
static inline void cpu_to_leguids(MSGUID *guid)
424 4f18b782 Jeff Cody
{
425 4f18b782 Jeff Cody
    cpu_to_le32s(&guid->data1);
426 4f18b782 Jeff Cody
    cpu_to_le16s(&guid->data2);
427 4f18b782 Jeff Cody
    cpu_to_le16s(&guid->data3);
428 4f18b782 Jeff Cody
}
429 4f18b782 Jeff Cody
430 0f48e8f0 Jeff Cody
void vhdx_header_le_import(VHDXHeader *h);
431 0f48e8f0 Jeff Cody
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h);
432 0f48e8f0 Jeff Cody
void vhdx_log_desc_le_import(VHDXLogDescriptor *d);
433 0f48e8f0 Jeff Cody
void vhdx_log_desc_le_export(VHDXLogDescriptor *d);
434 0f48e8f0 Jeff Cody
void vhdx_log_data_le_export(VHDXLogDataSector *d);
435 0f48e8f0 Jeff Cody
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr);
436 0f48e8f0 Jeff Cody
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr);
437 c325ee1d Jeff Cody
void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr);
438 c325ee1d Jeff Cody
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr);
439 c325ee1d Jeff Cody
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e);
440 c325ee1d Jeff Cody
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e);
441 c325ee1d Jeff Cody
void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr);
442 c325ee1d Jeff Cody
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr);
443 c325ee1d Jeff Cody
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e);
444 c325ee1d Jeff Cody
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e);
445 c3906c5e Jeff Cody
int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s);
446 c3906c5e Jeff Cody
447 203cdba3 Jeff Cody
#endif