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 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 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 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 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 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 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 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 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 */ 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 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 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 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 */ 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 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 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} 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