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