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