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 34void 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 52void 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 79void 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 88void 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 99void 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 108void 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 117void 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 132void 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 */ 149void 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 158void 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 167void 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 177void 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 */ 189void 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 197void 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 205void 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} 214void 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