10f48e8f0SJeff Cody /* 20f48e8f0SJeff Cody * Block driver for Hyper-V VHDX Images 30f48e8f0SJeff Cody * 40f48e8f0SJeff Cody * Copyright (c) 2013 Red Hat, Inc., 50f48e8f0SJeff Cody * 60f48e8f0SJeff Cody * Authors: 70f48e8f0SJeff Cody * Jeff Cody <jcody@redhat.com> 80f48e8f0SJeff Cody * 90f48e8f0SJeff Cody * This is based on the "VHDX Format Specification v1.00", published 8/25/2012 100f48e8f0SJeff Cody * by Microsoft: 110f48e8f0SJeff Cody * https://www.microsoft.com/en-us/download/details.aspx?id=34750 120f48e8f0SJeff Cody * 130f48e8f0SJeff Cody * This work is licensed under the terms of the GNU LGPL, version 2 or later. 140f48e8f0SJeff Cody * See the COPYING.LIB file in the top-level directory. 150f48e8f0SJeff Cody * 160f48e8f0SJeff Cody */ 170f48e8f0SJeff Cody 1880c71a24SPeter Maydell #include "qemu/osdep.h" 190f48e8f0SJeff Cody #include "block/block_int.h" 2058369e22SPaolo Bonzini #include "qemu/bswap.h" 210d8c41daSMichael S. Tsirkin #include "vhdx.h" 220f48e8f0SJeff Cody 230f48e8f0SJeff Cody /* 240f48e8f0SJeff Cody * All the VHDX formats on disk are little endian - the following 250f48e8f0SJeff Cody * are helper import/export functions to correctly convert 260f48e8f0SJeff Cody * endianness from disk read to native cpu format, and back again. 270f48e8f0SJeff Cody */ 280f48e8f0SJeff Cody 290f48e8f0SJeff Cody 300f48e8f0SJeff Cody /* VHDX File Header */ 310f48e8f0SJeff Cody 320f48e8f0SJeff Cody vhdx_header_le_import(VHDXHeader * h)330f48e8f0SJeff Codyvoid vhdx_header_le_import(VHDXHeader *h) 340f48e8f0SJeff Cody { 350f48e8f0SJeff Cody assert(h != NULL); 360f48e8f0SJeff Cody 37*1229e46dSPeter Maydell h->signature = le32_to_cpu(h->signature); 38*1229e46dSPeter Maydell h->checksum = le32_to_cpu(h->checksum); 39*1229e46dSPeter Maydell h->sequence_number = le64_to_cpu(h->sequence_number); 400f48e8f0SJeff Cody 410f48e8f0SJeff Cody leguid_to_cpus(&h->file_write_guid); 420f48e8f0SJeff Cody leguid_to_cpus(&h->data_write_guid); 430f48e8f0SJeff Cody leguid_to_cpus(&h->log_guid); 440f48e8f0SJeff Cody 45*1229e46dSPeter Maydell h->log_version = le16_to_cpu(h->log_version); 46*1229e46dSPeter Maydell h->version = le16_to_cpu(h->version); 47*1229e46dSPeter Maydell h->log_length = le32_to_cpu(h->log_length); 48*1229e46dSPeter Maydell h->log_offset = le64_to_cpu(h->log_offset); 490f48e8f0SJeff Cody } 500f48e8f0SJeff Cody vhdx_header_le_export(VHDXHeader * orig_h,VHDXHeader * new_h)510f48e8f0SJeff Codyvoid vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h) 520f48e8f0SJeff Cody { 530f48e8f0SJeff Cody assert(orig_h != NULL); 540f48e8f0SJeff Cody assert(new_h != NULL); 550f48e8f0SJeff Cody 560f48e8f0SJeff Cody new_h->signature = cpu_to_le32(orig_h->signature); 570f48e8f0SJeff Cody new_h->checksum = cpu_to_le32(orig_h->checksum); 580f48e8f0SJeff Cody new_h->sequence_number = cpu_to_le64(orig_h->sequence_number); 590f48e8f0SJeff Cody 600f48e8f0SJeff Cody new_h->file_write_guid = orig_h->file_write_guid; 610f48e8f0SJeff Cody new_h->data_write_guid = orig_h->data_write_guid; 620f48e8f0SJeff Cody new_h->log_guid = orig_h->log_guid; 630f48e8f0SJeff Cody 640f48e8f0SJeff Cody cpu_to_leguids(&new_h->file_write_guid); 650f48e8f0SJeff Cody cpu_to_leguids(&new_h->data_write_guid); 660f48e8f0SJeff Cody cpu_to_leguids(&new_h->log_guid); 670f48e8f0SJeff Cody 680f48e8f0SJeff Cody new_h->log_version = cpu_to_le16(orig_h->log_version); 690f48e8f0SJeff Cody new_h->version = cpu_to_le16(orig_h->version); 700f48e8f0SJeff Cody new_h->log_length = cpu_to_le32(orig_h->log_length); 710f48e8f0SJeff Cody new_h->log_offset = cpu_to_le64(orig_h->log_offset); 720f48e8f0SJeff Cody } 730f48e8f0SJeff Cody 740f48e8f0SJeff Cody 750f48e8f0SJeff Cody /* VHDX Log Headers */ 760f48e8f0SJeff Cody 770f48e8f0SJeff Cody vhdx_log_desc_le_import(VHDXLogDescriptor * d)780f48e8f0SJeff Codyvoid vhdx_log_desc_le_import(VHDXLogDescriptor *d) 790f48e8f0SJeff Cody { 800f48e8f0SJeff Cody assert(d != NULL); 810f48e8f0SJeff Cody 82*1229e46dSPeter Maydell d->signature = le32_to_cpu(d->signature); 83*1229e46dSPeter Maydell d->file_offset = le64_to_cpu(d->file_offset); 84*1229e46dSPeter Maydell d->sequence_number = le64_to_cpu(d->sequence_number); 850f48e8f0SJeff Cody } 860f48e8f0SJeff Cody vhdx_log_desc_le_export(VHDXLogDescriptor * d)870f48e8f0SJeff Codyvoid vhdx_log_desc_le_export(VHDXLogDescriptor *d) 880f48e8f0SJeff Cody { 890f48e8f0SJeff Cody assert(d != NULL); 900f48e8f0SJeff Cody 91*1229e46dSPeter Maydell d->signature = cpu_to_le32(d->signature); 92*1229e46dSPeter Maydell d->trailing_bytes = cpu_to_le32(d->trailing_bytes); 93*1229e46dSPeter Maydell d->leading_bytes = cpu_to_le64(d->leading_bytes); 94*1229e46dSPeter Maydell d->file_offset = cpu_to_le64(d->file_offset); 95*1229e46dSPeter Maydell d->sequence_number = cpu_to_le64(d->sequence_number); 960f48e8f0SJeff Cody } 970f48e8f0SJeff Cody vhdx_log_data_le_import(VHDXLogDataSector * d)984f75b52aSJeff Codyvoid vhdx_log_data_le_import(VHDXLogDataSector *d) 994f75b52aSJeff Cody { 1004f75b52aSJeff Cody assert(d != NULL); 1014f75b52aSJeff Cody 102*1229e46dSPeter Maydell d->data_signature = le32_to_cpu(d->data_signature); 103*1229e46dSPeter Maydell d->sequence_high = le32_to_cpu(d->sequence_high); 104*1229e46dSPeter Maydell d->sequence_low = le32_to_cpu(d->sequence_low); 1054f75b52aSJeff Cody } 1064f75b52aSJeff Cody vhdx_log_data_le_export(VHDXLogDataSector * d)1070f48e8f0SJeff Codyvoid vhdx_log_data_le_export(VHDXLogDataSector *d) 1080f48e8f0SJeff Cody { 1090f48e8f0SJeff Cody assert(d != NULL); 1100f48e8f0SJeff Cody 111*1229e46dSPeter Maydell d->data_signature = cpu_to_le32(d->data_signature); 112*1229e46dSPeter Maydell d->sequence_high = cpu_to_le32(d->sequence_high); 113*1229e46dSPeter Maydell d->sequence_low = cpu_to_le32(d->sequence_low); 1140f48e8f0SJeff Cody } 1150f48e8f0SJeff Cody vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader * hdr)1160f48e8f0SJeff Codyvoid vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr) 1170f48e8f0SJeff Cody { 1180f48e8f0SJeff Cody assert(hdr != NULL); 1190f48e8f0SJeff Cody 120*1229e46dSPeter Maydell hdr->signature = le32_to_cpu(hdr->signature); 121*1229e46dSPeter Maydell hdr->checksum = le32_to_cpu(hdr->checksum); 122*1229e46dSPeter Maydell hdr->entry_length = le32_to_cpu(hdr->entry_length); 123*1229e46dSPeter Maydell hdr->tail = le32_to_cpu(hdr->tail); 124*1229e46dSPeter Maydell hdr->sequence_number = le64_to_cpu(hdr->sequence_number); 125*1229e46dSPeter Maydell hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count); 1260f48e8f0SJeff Cody leguid_to_cpus(&hdr->log_guid); 127*1229e46dSPeter Maydell hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset); 128*1229e46dSPeter Maydell hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset); 1290f48e8f0SJeff Cody } 1300f48e8f0SJeff Cody vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader * hdr)1310f48e8f0SJeff Codyvoid vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr) 1320f48e8f0SJeff Cody { 1330f48e8f0SJeff Cody assert(hdr != NULL); 1340f48e8f0SJeff Cody 135*1229e46dSPeter Maydell hdr->signature = cpu_to_le32(hdr->signature); 136*1229e46dSPeter Maydell hdr->checksum = cpu_to_le32(hdr->checksum); 137*1229e46dSPeter Maydell hdr->entry_length = cpu_to_le32(hdr->entry_length); 138*1229e46dSPeter Maydell hdr->tail = cpu_to_le32(hdr->tail); 139*1229e46dSPeter Maydell hdr->sequence_number = cpu_to_le64(hdr->sequence_number); 140*1229e46dSPeter Maydell hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count); 1410f48e8f0SJeff Cody cpu_to_leguids(&hdr->log_guid); 142*1229e46dSPeter Maydell hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset); 143*1229e46dSPeter Maydell hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset); 1440f48e8f0SJeff Cody } 1450f48e8f0SJeff Cody 1460f48e8f0SJeff Cody 147c325ee1dSJeff Cody /* Region table entries */ vhdx_region_header_le_import(VHDXRegionTableHeader * hdr)148c325ee1dSJeff Codyvoid vhdx_region_header_le_import(VHDXRegionTableHeader *hdr) 149c325ee1dSJeff Cody { 150c325ee1dSJeff Cody assert(hdr != NULL); 151c325ee1dSJeff Cody 152*1229e46dSPeter Maydell hdr->signature = le32_to_cpu(hdr->signature); 153*1229e46dSPeter Maydell hdr->checksum = le32_to_cpu(hdr->checksum); 154*1229e46dSPeter Maydell hdr->entry_count = le32_to_cpu(hdr->entry_count); 155c325ee1dSJeff Cody } 156c325ee1dSJeff Cody vhdx_region_header_le_export(VHDXRegionTableHeader * hdr)157c325ee1dSJeff Codyvoid vhdx_region_header_le_export(VHDXRegionTableHeader *hdr) 158c325ee1dSJeff Cody { 159c325ee1dSJeff Cody assert(hdr != NULL); 160c325ee1dSJeff Cody 161*1229e46dSPeter Maydell hdr->signature = cpu_to_le32(hdr->signature); 162*1229e46dSPeter Maydell hdr->checksum = cpu_to_le32(hdr->checksum); 163*1229e46dSPeter Maydell hdr->entry_count = cpu_to_le32(hdr->entry_count); 164c325ee1dSJeff Cody } 165c325ee1dSJeff Cody vhdx_region_entry_le_import(VHDXRegionTableEntry * e)166c325ee1dSJeff Codyvoid vhdx_region_entry_le_import(VHDXRegionTableEntry *e) 167c325ee1dSJeff Cody { 168c325ee1dSJeff Cody assert(e != NULL); 169c325ee1dSJeff Cody 170c325ee1dSJeff Cody leguid_to_cpus(&e->guid); 171*1229e46dSPeter Maydell e->file_offset = le64_to_cpu(e->file_offset); 172*1229e46dSPeter Maydell e->length = le32_to_cpu(e->length); 173*1229e46dSPeter Maydell e->data_bits = le32_to_cpu(e->data_bits); 174c325ee1dSJeff Cody } 175c325ee1dSJeff Cody vhdx_region_entry_le_export(VHDXRegionTableEntry * e)176c325ee1dSJeff Codyvoid vhdx_region_entry_le_export(VHDXRegionTableEntry *e) 177c325ee1dSJeff Cody { 178c325ee1dSJeff Cody assert(e != NULL); 179c325ee1dSJeff Cody 180c325ee1dSJeff Cody cpu_to_leguids(&e->guid); 181*1229e46dSPeter Maydell e->file_offset = cpu_to_le64(e->file_offset); 182*1229e46dSPeter Maydell e->length = cpu_to_le32(e->length); 183*1229e46dSPeter Maydell e->data_bits = cpu_to_le32(e->data_bits); 184c325ee1dSJeff Cody } 185c325ee1dSJeff Cody 186c325ee1dSJeff Cody 187c325ee1dSJeff Cody /* Metadata headers & table */ vhdx_metadata_header_le_import(VHDXMetadataTableHeader * hdr)188c325ee1dSJeff Codyvoid vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr) 189c325ee1dSJeff Cody { 190c325ee1dSJeff Cody assert(hdr != NULL); 191c325ee1dSJeff Cody 192*1229e46dSPeter Maydell hdr->signature = le64_to_cpu(hdr->signature); 193*1229e46dSPeter Maydell hdr->entry_count = le16_to_cpu(hdr->entry_count); 194c325ee1dSJeff Cody } 195c325ee1dSJeff Cody vhdx_metadata_header_le_export(VHDXMetadataTableHeader * hdr)196c325ee1dSJeff Codyvoid vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr) 197c325ee1dSJeff Cody { 198c325ee1dSJeff Cody assert(hdr != NULL); 199c325ee1dSJeff Cody 200*1229e46dSPeter Maydell hdr->signature = cpu_to_le64(hdr->signature); 201*1229e46dSPeter Maydell hdr->entry_count = cpu_to_le16(hdr->entry_count); 202c325ee1dSJeff Cody } 203c325ee1dSJeff Cody vhdx_metadata_entry_le_import(VHDXMetadataTableEntry * e)204c325ee1dSJeff Codyvoid vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e) 205c325ee1dSJeff Cody { 206c325ee1dSJeff Cody assert(e != NULL); 207c325ee1dSJeff Cody 208c325ee1dSJeff Cody leguid_to_cpus(&e->item_id); 209*1229e46dSPeter Maydell e->offset = le32_to_cpu(e->offset); 210*1229e46dSPeter Maydell e->length = le32_to_cpu(e->length); 211*1229e46dSPeter Maydell e->data_bits = le32_to_cpu(e->data_bits); 212c325ee1dSJeff Cody } vhdx_metadata_entry_le_export(VHDXMetadataTableEntry * e)213c325ee1dSJeff Codyvoid vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e) 214c325ee1dSJeff Cody { 215c325ee1dSJeff Cody assert(e != NULL); 216c325ee1dSJeff Cody 217c325ee1dSJeff Cody cpu_to_leguids(&e->item_id); 218*1229e46dSPeter Maydell e->offset = cpu_to_le32(e->offset); 219*1229e46dSPeter Maydell e->length = cpu_to_le32(e->length); 220*1229e46dSPeter Maydell e->data_bits = cpu_to_le32(e->data_bits); 221c325ee1dSJeff Cody } 222