xref: /qemu/block/vhdx-endian.c (revision a8d25326)
10f48e8f0SJeff Cody /*
20f48e8f0SJeff Cody  * Block driver for Hyper-V VHDX Images
30f48e8f0SJeff Cody  *
40f48e8f0SJeff Cody  * Copyright (c) 2013 Red Hat, Inc.,
50f48e8f0SJeff Cody  *
60f48e8f0SJeff Cody  * Authors:
70f48e8f0SJeff Cody  *  Jeff Cody <jcody@redhat.com>
80f48e8f0SJeff Cody  *
90f48e8f0SJeff Cody  *  This is based on the "VHDX Format Specification v1.00", published 8/25/2012
100f48e8f0SJeff Cody  *  by Microsoft:
110f48e8f0SJeff Cody  *      https://www.microsoft.com/en-us/download/details.aspx?id=34750
120f48e8f0SJeff Cody  *
130f48e8f0SJeff Cody  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
140f48e8f0SJeff Cody  * See the COPYING.LIB file in the top-level directory.
150f48e8f0SJeff Cody  *
160f48e8f0SJeff Cody  */
170f48e8f0SJeff Cody 
1880c71a24SPeter Maydell #include "qemu/osdep.h"
190f48e8f0SJeff Cody #include "block/block_int.h"
2058369e22SPaolo Bonzini #include "qemu/bswap.h"
210d8c41daSMichael S. Tsirkin #include "vhdx.h"
220f48e8f0SJeff Cody 
230f48e8f0SJeff Cody /*
240f48e8f0SJeff Cody  * All the VHDX formats on disk are little endian - the following
250f48e8f0SJeff Cody  * are helper import/export functions to correctly convert
260f48e8f0SJeff Cody  * endianness from disk read to native cpu format, and back again.
270f48e8f0SJeff Cody  */
280f48e8f0SJeff Cody 
290f48e8f0SJeff Cody 
300f48e8f0SJeff Cody /* VHDX File Header */
310f48e8f0SJeff Cody 
320f48e8f0SJeff Cody 
vhdx_header_le_import(VHDXHeader * h)330f48e8f0SJeff Cody void vhdx_header_le_import(VHDXHeader *h)
340f48e8f0SJeff Cody {
350f48e8f0SJeff Cody     assert(h != NULL);
360f48e8f0SJeff Cody 
37*1229e46dSPeter Maydell     h->signature = le32_to_cpu(h->signature);
38*1229e46dSPeter Maydell     h->checksum = le32_to_cpu(h->checksum);
39*1229e46dSPeter Maydell     h->sequence_number = le64_to_cpu(h->sequence_number);
400f48e8f0SJeff Cody 
410f48e8f0SJeff Cody     leguid_to_cpus(&h->file_write_guid);
420f48e8f0SJeff Cody     leguid_to_cpus(&h->data_write_guid);
430f48e8f0SJeff Cody     leguid_to_cpus(&h->log_guid);
440f48e8f0SJeff Cody 
45*1229e46dSPeter Maydell     h->log_version = le16_to_cpu(h->log_version);
46*1229e46dSPeter Maydell     h->version = le16_to_cpu(h->version);
47*1229e46dSPeter Maydell     h->log_length = le32_to_cpu(h->log_length);
48*1229e46dSPeter Maydell     h->log_offset = le64_to_cpu(h->log_offset);
490f48e8f0SJeff Cody }
500f48e8f0SJeff Cody 
vhdx_header_le_export(VHDXHeader * orig_h,VHDXHeader * new_h)510f48e8f0SJeff Cody void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
520f48e8f0SJeff Cody {
530f48e8f0SJeff Cody     assert(orig_h != NULL);
540f48e8f0SJeff Cody     assert(new_h != NULL);
550f48e8f0SJeff Cody 
560f48e8f0SJeff Cody     new_h->signature       = cpu_to_le32(orig_h->signature);
570f48e8f0SJeff Cody     new_h->checksum        = cpu_to_le32(orig_h->checksum);
580f48e8f0SJeff Cody     new_h->sequence_number = cpu_to_le64(orig_h->sequence_number);
590f48e8f0SJeff Cody 
600f48e8f0SJeff Cody     new_h->file_write_guid = orig_h->file_write_guid;
610f48e8f0SJeff Cody     new_h->data_write_guid = orig_h->data_write_guid;
620f48e8f0SJeff Cody     new_h->log_guid        = orig_h->log_guid;
630f48e8f0SJeff Cody 
640f48e8f0SJeff Cody     cpu_to_leguids(&new_h->file_write_guid);
650f48e8f0SJeff Cody     cpu_to_leguids(&new_h->data_write_guid);
660f48e8f0SJeff Cody     cpu_to_leguids(&new_h->log_guid);
670f48e8f0SJeff Cody 
680f48e8f0SJeff Cody     new_h->log_version     = cpu_to_le16(orig_h->log_version);
690f48e8f0SJeff Cody     new_h->version         = cpu_to_le16(orig_h->version);
700f48e8f0SJeff Cody     new_h->log_length      = cpu_to_le32(orig_h->log_length);
710f48e8f0SJeff Cody     new_h->log_offset      = cpu_to_le64(orig_h->log_offset);
720f48e8f0SJeff Cody }
730f48e8f0SJeff Cody 
740f48e8f0SJeff Cody 
750f48e8f0SJeff Cody /* VHDX Log Headers */
760f48e8f0SJeff Cody 
770f48e8f0SJeff Cody 
vhdx_log_desc_le_import(VHDXLogDescriptor * d)780f48e8f0SJeff Cody void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
790f48e8f0SJeff Cody {
800f48e8f0SJeff Cody     assert(d != NULL);
810f48e8f0SJeff Cody 
82*1229e46dSPeter Maydell     d->signature = le32_to_cpu(d->signature);
83*1229e46dSPeter Maydell     d->file_offset = le64_to_cpu(d->file_offset);
84*1229e46dSPeter Maydell     d->sequence_number = le64_to_cpu(d->sequence_number);
850f48e8f0SJeff Cody }
860f48e8f0SJeff Cody 
vhdx_log_desc_le_export(VHDXLogDescriptor * d)870f48e8f0SJeff Cody void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
880f48e8f0SJeff Cody {
890f48e8f0SJeff Cody     assert(d != NULL);
900f48e8f0SJeff Cody 
91*1229e46dSPeter Maydell     d->signature = cpu_to_le32(d->signature);
92*1229e46dSPeter Maydell     d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
93*1229e46dSPeter Maydell     d->leading_bytes = cpu_to_le64(d->leading_bytes);
94*1229e46dSPeter Maydell     d->file_offset = cpu_to_le64(d->file_offset);
95*1229e46dSPeter Maydell     d->sequence_number = cpu_to_le64(d->sequence_number);
960f48e8f0SJeff Cody }
970f48e8f0SJeff Cody 
vhdx_log_data_le_import(VHDXLogDataSector * d)984f75b52aSJeff Cody void vhdx_log_data_le_import(VHDXLogDataSector *d)
994f75b52aSJeff Cody {
1004f75b52aSJeff Cody     assert(d != NULL);
1014f75b52aSJeff Cody 
102*1229e46dSPeter Maydell     d->data_signature = le32_to_cpu(d->data_signature);
103*1229e46dSPeter Maydell     d->sequence_high = le32_to_cpu(d->sequence_high);
104*1229e46dSPeter Maydell     d->sequence_low = le32_to_cpu(d->sequence_low);
1054f75b52aSJeff Cody }
1064f75b52aSJeff Cody 
vhdx_log_data_le_export(VHDXLogDataSector * d)1070f48e8f0SJeff Cody void vhdx_log_data_le_export(VHDXLogDataSector *d)
1080f48e8f0SJeff Cody {
1090f48e8f0SJeff Cody     assert(d != NULL);
1100f48e8f0SJeff Cody 
111*1229e46dSPeter Maydell     d->data_signature = cpu_to_le32(d->data_signature);
112*1229e46dSPeter Maydell     d->sequence_high = cpu_to_le32(d->sequence_high);
113*1229e46dSPeter Maydell     d->sequence_low = cpu_to_le32(d->sequence_low);
1140f48e8f0SJeff Cody }
1150f48e8f0SJeff Cody 
vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader * hdr)1160f48e8f0SJeff Cody void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
1170f48e8f0SJeff Cody {
1180f48e8f0SJeff Cody     assert(hdr != NULL);
1190f48e8f0SJeff Cody 
120*1229e46dSPeter Maydell     hdr->signature = le32_to_cpu(hdr->signature);
121*1229e46dSPeter Maydell     hdr->checksum = le32_to_cpu(hdr->checksum);
122*1229e46dSPeter Maydell     hdr->entry_length = le32_to_cpu(hdr->entry_length);
123*1229e46dSPeter Maydell     hdr->tail = le32_to_cpu(hdr->tail);
124*1229e46dSPeter Maydell     hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
125*1229e46dSPeter Maydell     hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
1260f48e8f0SJeff Cody     leguid_to_cpus(&hdr->log_guid);
127*1229e46dSPeter Maydell     hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
128*1229e46dSPeter Maydell     hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
1290f48e8f0SJeff Cody }
1300f48e8f0SJeff Cody 
vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader * hdr)1310f48e8f0SJeff Cody void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
1320f48e8f0SJeff Cody {
1330f48e8f0SJeff Cody     assert(hdr != NULL);
1340f48e8f0SJeff Cody 
135*1229e46dSPeter Maydell     hdr->signature = cpu_to_le32(hdr->signature);
136*1229e46dSPeter Maydell     hdr->checksum = cpu_to_le32(hdr->checksum);
137*1229e46dSPeter Maydell     hdr->entry_length = cpu_to_le32(hdr->entry_length);
138*1229e46dSPeter Maydell     hdr->tail = cpu_to_le32(hdr->tail);
139*1229e46dSPeter Maydell     hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
140*1229e46dSPeter Maydell     hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
1410f48e8f0SJeff Cody     cpu_to_leguids(&hdr->log_guid);
142*1229e46dSPeter Maydell     hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
143*1229e46dSPeter Maydell     hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
1440f48e8f0SJeff Cody }
1450f48e8f0SJeff Cody 
1460f48e8f0SJeff Cody 
147c325ee1dSJeff Cody /* Region table entries */
vhdx_region_header_le_import(VHDXRegionTableHeader * hdr)148c325ee1dSJeff Cody void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
149c325ee1dSJeff Cody {
150c325ee1dSJeff Cody     assert(hdr != NULL);
151c325ee1dSJeff Cody 
152*1229e46dSPeter Maydell     hdr->signature = le32_to_cpu(hdr->signature);
153*1229e46dSPeter Maydell     hdr->checksum = le32_to_cpu(hdr->checksum);
154*1229e46dSPeter Maydell     hdr->entry_count = le32_to_cpu(hdr->entry_count);
155c325ee1dSJeff Cody }
156c325ee1dSJeff Cody 
vhdx_region_header_le_export(VHDXRegionTableHeader * hdr)157c325ee1dSJeff Cody void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
158c325ee1dSJeff Cody {
159c325ee1dSJeff Cody     assert(hdr != NULL);
160c325ee1dSJeff Cody 
161*1229e46dSPeter Maydell     hdr->signature = cpu_to_le32(hdr->signature);
162*1229e46dSPeter Maydell     hdr->checksum = cpu_to_le32(hdr->checksum);
163*1229e46dSPeter Maydell     hdr->entry_count = cpu_to_le32(hdr->entry_count);
164c325ee1dSJeff Cody }
165c325ee1dSJeff Cody 
vhdx_region_entry_le_import(VHDXRegionTableEntry * e)166c325ee1dSJeff Cody void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
167c325ee1dSJeff Cody {
168c325ee1dSJeff Cody     assert(e != NULL);
169c325ee1dSJeff Cody 
170c325ee1dSJeff Cody     leguid_to_cpus(&e->guid);
171*1229e46dSPeter Maydell     e->file_offset = le64_to_cpu(e->file_offset);
172*1229e46dSPeter Maydell     e->length = le32_to_cpu(e->length);
173*1229e46dSPeter Maydell     e->data_bits = le32_to_cpu(e->data_bits);
174c325ee1dSJeff Cody }
175c325ee1dSJeff Cody 
vhdx_region_entry_le_export(VHDXRegionTableEntry * e)176c325ee1dSJeff Cody void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
177c325ee1dSJeff Cody {
178c325ee1dSJeff Cody     assert(e != NULL);
179c325ee1dSJeff Cody 
180c325ee1dSJeff Cody     cpu_to_leguids(&e->guid);
181*1229e46dSPeter Maydell     e->file_offset = cpu_to_le64(e->file_offset);
182*1229e46dSPeter Maydell     e->length = cpu_to_le32(e->length);
183*1229e46dSPeter Maydell     e->data_bits = cpu_to_le32(e->data_bits);
184c325ee1dSJeff Cody }
185c325ee1dSJeff Cody 
186c325ee1dSJeff Cody 
187c325ee1dSJeff Cody /* Metadata headers & table */
vhdx_metadata_header_le_import(VHDXMetadataTableHeader * hdr)188c325ee1dSJeff Cody void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
189c325ee1dSJeff Cody {
190c325ee1dSJeff Cody     assert(hdr != NULL);
191c325ee1dSJeff Cody 
192*1229e46dSPeter Maydell     hdr->signature = le64_to_cpu(hdr->signature);
193*1229e46dSPeter Maydell     hdr->entry_count = le16_to_cpu(hdr->entry_count);
194c325ee1dSJeff Cody }
195c325ee1dSJeff Cody 
vhdx_metadata_header_le_export(VHDXMetadataTableHeader * hdr)196c325ee1dSJeff Cody void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
197c325ee1dSJeff Cody {
198c325ee1dSJeff Cody     assert(hdr != NULL);
199c325ee1dSJeff Cody 
200*1229e46dSPeter Maydell     hdr->signature = cpu_to_le64(hdr->signature);
201*1229e46dSPeter Maydell     hdr->entry_count = cpu_to_le16(hdr->entry_count);
202c325ee1dSJeff Cody }
203c325ee1dSJeff Cody 
vhdx_metadata_entry_le_import(VHDXMetadataTableEntry * e)204c325ee1dSJeff Cody void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
205c325ee1dSJeff Cody {
206c325ee1dSJeff Cody     assert(e != NULL);
207c325ee1dSJeff Cody 
208c325ee1dSJeff Cody     leguid_to_cpus(&e->item_id);
209*1229e46dSPeter Maydell     e->offset = le32_to_cpu(e->offset);
210*1229e46dSPeter Maydell     e->length = le32_to_cpu(e->length);
211*1229e46dSPeter Maydell     e->data_bits = le32_to_cpu(e->data_bits);
212c325ee1dSJeff Cody }
vhdx_metadata_entry_le_export(VHDXMetadataTableEntry * e)213c325ee1dSJeff Cody void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
214c325ee1dSJeff Cody {
215c325ee1dSJeff Cody     assert(e != NULL);
216c325ee1dSJeff Cody 
217c325ee1dSJeff Cody     cpu_to_leguids(&e->item_id);
218*1229e46dSPeter Maydell     e->offset = cpu_to_le32(e->offset);
219*1229e46dSPeter Maydell     e->length = cpu_to_le32(e->length);
220*1229e46dSPeter Maydell     e->data_bits = cpu_to_le32(e->data_bits);
221c325ee1dSJeff Cody }
222