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 18 #include "qemu/osdep.h" 19 #include "block/block_int.h" 20 #include "qemu/bswap.h" 21 #include "vhdx.h" 22 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 vhdx_header_le_import(VHDXHeader * h)33void vhdx_header_le_import(VHDXHeader *h) 34 { 35 assert(h != NULL); 36 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); 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 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); 49 } 50 vhdx_header_le_export(VHDXHeader * orig_h,VHDXHeader * new_h)51void 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 vhdx_log_desc_le_import(VHDXLogDescriptor * d)78void vhdx_log_desc_le_import(VHDXLogDescriptor *d) 79 { 80 assert(d != NULL); 81 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); 85 } 86 vhdx_log_desc_le_export(VHDXLogDescriptor * d)87void vhdx_log_desc_le_export(VHDXLogDescriptor *d) 88 { 89 assert(d != NULL); 90 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); 96 } 97 vhdx_log_data_le_import(VHDXLogDataSector * d)98void vhdx_log_data_le_import(VHDXLogDataSector *d) 99 { 100 assert(d != NULL); 101 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); 105 } 106 vhdx_log_data_le_export(VHDXLogDataSector * d)107void vhdx_log_data_le_export(VHDXLogDataSector *d) 108 { 109 assert(d != NULL); 110 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); 114 } 115 vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader * hdr)116void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr) 117 { 118 assert(hdr != NULL); 119 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); 126 leguid_to_cpus(&hdr->log_guid); 127 hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset); 128 hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset); 129 } 130 vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader * hdr)131void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr) 132 { 133 assert(hdr != NULL); 134 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); 141 cpu_to_leguids(&hdr->log_guid); 142 hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset); 143 hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset); 144 } 145 146 147 /* Region table entries */ vhdx_region_header_le_import(VHDXRegionTableHeader * hdr)148void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr) 149 { 150 assert(hdr != NULL); 151 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); 155 } 156 vhdx_region_header_le_export(VHDXRegionTableHeader * hdr)157void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr) 158 { 159 assert(hdr != NULL); 160 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); 164 } 165 vhdx_region_entry_le_import(VHDXRegionTableEntry * e)166void vhdx_region_entry_le_import(VHDXRegionTableEntry *e) 167 { 168 assert(e != NULL); 169 170 leguid_to_cpus(&e->guid); 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); 174 } 175 vhdx_region_entry_le_export(VHDXRegionTableEntry * e)176void vhdx_region_entry_le_export(VHDXRegionTableEntry *e) 177 { 178 assert(e != NULL); 179 180 cpu_to_leguids(&e->guid); 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); 184 } 185 186 187 /* Metadata headers & table */ vhdx_metadata_header_le_import(VHDXMetadataTableHeader * hdr)188void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr) 189 { 190 assert(hdr != NULL); 191 192 hdr->signature = le64_to_cpu(hdr->signature); 193 hdr->entry_count = le16_to_cpu(hdr->entry_count); 194 } 195 vhdx_metadata_header_le_export(VHDXMetadataTableHeader * hdr)196void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr) 197 { 198 assert(hdr != NULL); 199 200 hdr->signature = cpu_to_le64(hdr->signature); 201 hdr->entry_count = cpu_to_le16(hdr->entry_count); 202 } 203 vhdx_metadata_entry_le_import(VHDXMetadataTableEntry * e)204void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e) 205 { 206 assert(e != NULL); 207 208 leguid_to_cpus(&e->item_id); 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); 212 } vhdx_metadata_entry_le_export(VHDXMetadataTableEntry * e)213void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e) 214 { 215 assert(e != NULL); 216 217 cpu_to_leguids(&e->item_id); 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); 221 } 222