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