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 37void 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 55void 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 82void 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 91void 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 102void 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 111void 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 120void 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 135void 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 */ 152void 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 161void 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 170void 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 180void 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 */ 192void 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 200void 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 208void 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} 217void 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