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