]>
Commit | Line | Data |
---|---|---|
0f48e8f0 JC |
1 | /* |
2 | * Block driver for Hyper-V VHDX Images | |
3 | * | |
4 | * Copyright (c) 2013 Red Hat, Inc., | |
5 | * | |
6 | * Authors: | |
7 | * Jeff Cody <[email protected]> | |
8 | * | |
9 | * This is based on the "VHDX Format Specification v1.00", published 8/25/2012 | |
10 | * by Microsoft: | |
11 | * https://www.microsoft.com/en-us/download/details.aspx?id=34750 | |
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 | ||
80c71a24 | 18 | #include "qemu/osdep.h" |
0f48e8f0 JC |
19 | #include "qemu-common.h" |
20 | #include "block/block_int.h" | |
58369e22 | 21 | #include "qemu/bswap.h" |
0f48e8f0 JC |
22 | #include "block/vhdx.h" |
23 | ||
24 | #include <uuid/uuid.h> | |
25 | ||
26 | ||
27 | /* | |
28 | * All the VHDX formats on disk are little endian - the following | |
29 | * are helper import/export functions to correctly convert | |
30 | * endianness from disk read to native cpu format, and back again. | |
31 | */ | |
32 | ||
33 | ||
34 | /* VHDX File Header */ | |
35 | ||
36 | ||
37 | void vhdx_header_le_import(VHDXHeader *h) | |
38 | { | |
39 | assert(h != NULL); | |
40 | ||
41 | le32_to_cpus(&h->signature); | |
42 | le32_to_cpus(&h->checksum); | |
43 | le64_to_cpus(&h->sequence_number); | |
44 | ||
45 | leguid_to_cpus(&h->file_write_guid); | |
46 | leguid_to_cpus(&h->data_write_guid); | |
47 | leguid_to_cpus(&h->log_guid); | |
48 | ||
49 | le16_to_cpus(&h->log_version); | |
50 | le16_to_cpus(&h->version); | |
51 | le32_to_cpus(&h->log_length); | |
52 | le64_to_cpus(&h->log_offset); | |
53 | } | |
54 | ||
55 | void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h) | |
56 | { | |
57 | assert(orig_h != NULL); | |
58 | assert(new_h != NULL); | |
59 | ||
60 | new_h->signature = cpu_to_le32(orig_h->signature); | |
61 | new_h->checksum = cpu_to_le32(orig_h->checksum); | |
62 | new_h->sequence_number = cpu_to_le64(orig_h->sequence_number); | |
63 | ||
64 | new_h->file_write_guid = orig_h->file_write_guid; | |
65 | new_h->data_write_guid = orig_h->data_write_guid; | |
66 | new_h->log_guid = orig_h->log_guid; | |
67 | ||
68 | cpu_to_leguids(&new_h->file_write_guid); | |
69 | cpu_to_leguids(&new_h->data_write_guid); | |
70 | cpu_to_leguids(&new_h->log_guid); | |
71 | ||
72 | new_h->log_version = cpu_to_le16(orig_h->log_version); | |
73 | new_h->version = cpu_to_le16(orig_h->version); | |
74 | new_h->log_length = cpu_to_le32(orig_h->log_length); | |
75 | new_h->log_offset = cpu_to_le64(orig_h->log_offset); | |
76 | } | |
77 | ||
78 | ||
79 | /* VHDX Log Headers */ | |
80 | ||
81 | ||
82 | void vhdx_log_desc_le_import(VHDXLogDescriptor *d) | |
83 | { | |
84 | assert(d != NULL); | |
85 | ||
86 | le32_to_cpus(&d->signature); | |
0f48e8f0 JC |
87 | le64_to_cpus(&d->file_offset); |
88 | le64_to_cpus(&d->sequence_number); | |
89 | } | |
90 | ||
91 | void vhdx_log_desc_le_export(VHDXLogDescriptor *d) | |
92 | { | |
93 | assert(d != NULL); | |
94 | ||
95 | cpu_to_le32s(&d->signature); | |
96 | cpu_to_le32s(&d->trailing_bytes); | |
97 | cpu_to_le64s(&d->leading_bytes); | |
98 | cpu_to_le64s(&d->file_offset); | |
99 | cpu_to_le64s(&d->sequence_number); | |
100 | } | |
101 | ||
4f75b52a JC |
102 | void vhdx_log_data_le_import(VHDXLogDataSector *d) |
103 | { | |
104 | assert(d != NULL); | |
105 | ||
106 | le32_to_cpus(&d->data_signature); | |
107 | le32_to_cpus(&d->sequence_high); | |
108 | le32_to_cpus(&d->sequence_low); | |
109 | } | |
110 | ||
0f48e8f0 JC |
111 | void vhdx_log_data_le_export(VHDXLogDataSector *d) |
112 | { | |
113 | assert(d != NULL); | |
114 | ||
115 | cpu_to_le32s(&d->data_signature); | |
116 | cpu_to_le32s(&d->sequence_high); | |
117 | cpu_to_le32s(&d->sequence_low); | |
118 | } | |
119 | ||
120 | void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr) | |
121 | { | |
122 | assert(hdr != NULL); | |
123 | ||
124 | le32_to_cpus(&hdr->signature); | |
125 | le32_to_cpus(&hdr->checksum); | |
126 | le32_to_cpus(&hdr->entry_length); | |
127 | le32_to_cpus(&hdr->tail); | |
128 | le64_to_cpus(&hdr->sequence_number); | |
129 | le32_to_cpus(&hdr->descriptor_count); | |
130 | leguid_to_cpus(&hdr->log_guid); | |
131 | le64_to_cpus(&hdr->flushed_file_offset); | |
132 | le64_to_cpus(&hdr->last_file_offset); | |
133 | } | |
134 | ||
135 | void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr) | |
136 | { | |
137 | assert(hdr != NULL); | |
138 | ||
139 | cpu_to_le32s(&hdr->signature); | |
140 | cpu_to_le32s(&hdr->checksum); | |
141 | cpu_to_le32s(&hdr->entry_length); | |
142 | cpu_to_le32s(&hdr->tail); | |
143 | cpu_to_le64s(&hdr->sequence_number); | |
144 | cpu_to_le32s(&hdr->descriptor_count); | |
145 | cpu_to_leguids(&hdr->log_guid); | |
146 | cpu_to_le64s(&hdr->flushed_file_offset); | |
147 | cpu_to_le64s(&hdr->last_file_offset); | |
148 | } | |
149 | ||
150 | ||
c325ee1d JC |
151 | /* Region table entries */ |
152 | void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr) | |
153 | { | |
154 | assert(hdr != NULL); | |
155 | ||
156 | le32_to_cpus(&hdr->signature); | |
157 | le32_to_cpus(&hdr->checksum); | |
158 | le32_to_cpus(&hdr->entry_count); | |
159 | } | |
160 | ||
161 | void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr) | |
162 | { | |
163 | assert(hdr != NULL); | |
164 | ||
165 | cpu_to_le32s(&hdr->signature); | |
166 | cpu_to_le32s(&hdr->checksum); | |
167 | cpu_to_le32s(&hdr->entry_count); | |
168 | } | |
169 | ||
170 | void vhdx_region_entry_le_import(VHDXRegionTableEntry *e) | |
171 | { | |
172 | assert(e != NULL); | |
173 | ||
174 | leguid_to_cpus(&e->guid); | |
175 | le64_to_cpus(&e->file_offset); | |
176 | le32_to_cpus(&e->length); | |
177 | le32_to_cpus(&e->data_bits); | |
178 | } | |
179 | ||
180 | void vhdx_region_entry_le_export(VHDXRegionTableEntry *e) | |
181 | { | |
182 | assert(e != NULL); | |
183 | ||
184 | cpu_to_leguids(&e->guid); | |
185 | cpu_to_le64s(&e->file_offset); | |
186 | cpu_to_le32s(&e->length); | |
187 | cpu_to_le32s(&e->data_bits); | |
188 | } | |
189 | ||
190 | ||
191 | /* Metadata headers & table */ | |
192 | void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr) | |
193 | { | |
194 | assert(hdr != NULL); | |
195 | ||
196 | le64_to_cpus(&hdr->signature); | |
197 | le16_to_cpus(&hdr->entry_count); | |
198 | } | |
199 | ||
200 | void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr) | |
201 | { | |
202 | assert(hdr != NULL); | |
203 | ||
204 | cpu_to_le64s(&hdr->signature); | |
205 | cpu_to_le16s(&hdr->entry_count); | |
206 | } | |
207 | ||
208 | void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e) | |
209 | { | |
210 | assert(e != NULL); | |
211 | ||
212 | leguid_to_cpus(&e->item_id); | |
213 | le32_to_cpus(&e->offset); | |
214 | le32_to_cpus(&e->length); | |
215 | le32_to_cpus(&e->data_bits); | |
216 | } | |
217 | void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e) | |
218 | { | |
219 | assert(e != NULL); | |
220 | ||
221 | cpu_to_leguids(&e->item_id); | |
222 | cpu_to_le32s(&e->offset); | |
223 | cpu_to_le32s(&e->length); | |
224 | cpu_to_le32s(&e->data_bits); | |
225 | } |