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 "block/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 le32_to_cpus(&h->signature); 39 le32_to_cpus(&h->checksum); 40 le64_to_cpus(&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 le16_to_cpus(&h->log_version); 47 le16_to_cpus(&h->version); 48 le32_to_cpus(&h->log_length); 49 le64_to_cpus(&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 le32_to_cpus(&d->signature); 84 le64_to_cpus(&d->file_offset); 85 le64_to_cpus(&d->sequence_number); 86 } 87 88 void vhdx_log_desc_le_export(VHDXLogDescriptor *d) 89 { 90 assert(d != NULL); 91 92 cpu_to_le32s(&d->signature); 93 cpu_to_le32s(&d->trailing_bytes); 94 cpu_to_le64s(&d->leading_bytes); 95 cpu_to_le64s(&d->file_offset); 96 cpu_to_le64s(&d->sequence_number); 97 } 98 99 void vhdx_log_data_le_import(VHDXLogDataSector *d) 100 { 101 assert(d != NULL); 102 103 le32_to_cpus(&d->data_signature); 104 le32_to_cpus(&d->sequence_high); 105 le32_to_cpus(&d->sequence_low); 106 } 107 108 void vhdx_log_data_le_export(VHDXLogDataSector *d) 109 { 110 assert(d != NULL); 111 112 cpu_to_le32s(&d->data_signature); 113 cpu_to_le32s(&d->sequence_high); 114 cpu_to_le32s(&d->sequence_low); 115 } 116 117 void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr) 118 { 119 assert(hdr != NULL); 120 121 le32_to_cpus(&hdr->signature); 122 le32_to_cpus(&hdr->checksum); 123 le32_to_cpus(&hdr->entry_length); 124 le32_to_cpus(&hdr->tail); 125 le64_to_cpus(&hdr->sequence_number); 126 le32_to_cpus(&hdr->descriptor_count); 127 leguid_to_cpus(&hdr->log_guid); 128 le64_to_cpus(&hdr->flushed_file_offset); 129 le64_to_cpus(&hdr->last_file_offset); 130 } 131 132 void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr) 133 { 134 assert(hdr != NULL); 135 136 cpu_to_le32s(&hdr->signature); 137 cpu_to_le32s(&hdr->checksum); 138 cpu_to_le32s(&hdr->entry_length); 139 cpu_to_le32s(&hdr->tail); 140 cpu_to_le64s(&hdr->sequence_number); 141 cpu_to_le32s(&hdr->descriptor_count); 142 cpu_to_leguids(&hdr->log_guid); 143 cpu_to_le64s(&hdr->flushed_file_offset); 144 cpu_to_le64s(&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 le32_to_cpus(&hdr->signature); 154 le32_to_cpus(&hdr->checksum); 155 le32_to_cpus(&hdr->entry_count); 156 } 157 158 void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr) 159 { 160 assert(hdr != NULL); 161 162 cpu_to_le32s(&hdr->signature); 163 cpu_to_le32s(&hdr->checksum); 164 cpu_to_le32s(&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 le64_to_cpus(&e->file_offset); 173 le32_to_cpus(&e->length); 174 le32_to_cpus(&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 cpu_to_le64s(&e->file_offset); 183 cpu_to_le32s(&e->length); 184 cpu_to_le32s(&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 le64_to_cpus(&hdr->signature); 194 le16_to_cpus(&hdr->entry_count); 195 } 196 197 void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr) 198 { 199 assert(hdr != NULL); 200 201 cpu_to_le64s(&hdr->signature); 202 cpu_to_le16s(&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 le32_to_cpus(&e->offset); 211 le32_to_cpus(&e->length); 212 le32_to_cpus(&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 cpu_to_le32s(&e->offset); 220 cpu_to_le32s(&e->length); 221 cpu_to_le32s(&e->data_bits); 222 } 223