74ed550334
This PR allows larger VHD image files. The size in question doesn't necessarily mean the size of the VHD file on disk. The size is the total size of the image emulated. This total size is in question. Without this patch, the total size allowed is 65535 * 16 * 255, or roughly 32gig. With this patch, the total size is calculated by who the creator of the image is, what the CHS values are, and possibly a total size of up to a limit of 2TB. Since the original code was ported from QEMU, I ported an updated QEMU code snippet. https://gitlab.com/qemu-project/qemu/-/blob/master/block/vpc.c?ref_type=heads#L305 This PR now allows VHD image files with a total size emulated less than or equal to 2TB.
197 lines
5.2 KiB
C++
197 lines
5.2 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
|
// $Id$
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Block driver for Connectix / Microsoft Virtual PC images (ported from QEMU)
|
|
//
|
|
// Copyright (c) 2005 Alex Beregszaszi
|
|
// Copyright (c) 2009 Kevin Wolf <kwolf@suse.de>
|
|
// Copyright (C) 2012-2021 The Bochs Project
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef BX_VPCIMG_H
|
|
#define BX_VPCIMG_H
|
|
|
|
#define HEADER_SIZE 512
|
|
|
|
enum vhd_type {
|
|
VHD_FIXED = 2,
|
|
VHD_DYNAMIC = 3,
|
|
VHD_DIFFERENCING = 4,
|
|
};
|
|
|
|
// Seconds since Jan 1, 2000 0:00:00 (UTC)
|
|
#define VHD_TIMESTAMP_BASE 946684800
|
|
|
|
// be*_to_cpu : convert disk (big) to host endianness
|
|
#if defined (BX_LITTLE_ENDIAN)
|
|
#define be16_to_cpu(val) bx_bswap16(val)
|
|
#define be32_to_cpu(val) bx_bswap32(val)
|
|
#define be64_to_cpu(val) bx_bswap64(val)
|
|
#define cpu_to_be32(val) bx_bswap32(val)
|
|
#else
|
|
#define be16_to_cpu(val) (val)
|
|
#define be32_to_cpu(val) (val)
|
|
#define be64_to_cpu(val) (val)
|
|
#define cpu_to_be32(val) (val)
|
|
#endif
|
|
|
|
Bit32u vpc_checksum(Bit8u *buf, size_t size);
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER<1300)
|
|
#pragma pack(push, 1)
|
|
#elif defined(__MWERKS__) && defined(macintosh)
|
|
#pragma options align=packed
|
|
#endif
|
|
|
|
// always big-endian
|
|
typedef
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
struct vhd_footer_t {
|
|
char creator[8]; // "conectix"
|
|
Bit32u features;
|
|
Bit32u version;
|
|
|
|
// Offset of next header structure, 0xFFFFFFFF if none
|
|
Bit64u data_offset;
|
|
|
|
// Seconds since Jan 1, 2000 0:00:00 (UTC)
|
|
Bit32u timestamp;
|
|
|
|
char creator_app[4]; // "vpc "
|
|
Bit16u major;
|
|
Bit16u minor;
|
|
char creator_os[4]; // "Wi2k"
|
|
|
|
Bit64u orig_size;
|
|
Bit64u size;
|
|
|
|
Bit16u cyls;
|
|
Bit8u heads;
|
|
Bit8u secs_per_cyl;
|
|
|
|
Bit32u type;
|
|
|
|
// Checksum of the Hard Disk Footer ("one's complement of the sum of all
|
|
// the bytes in the footer without the checksum field")
|
|
Bit32u checksum;
|
|
|
|
// UUID used to identify a parent hard disk (backing file)
|
|
Bit8u uuid[16];
|
|
|
|
Bit8u in_saved_state;
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
vhd_footer_t;
|
|
|
|
typedef
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
struct vhd_dyndisk_header_t {
|
|
Bit8u magic[8]; // "cxsparse"
|
|
|
|
// Offset of next header structure, 0xFFFFFFFF if none
|
|
Bit64u data_offset;
|
|
|
|
// Offset of the Block Allocation Table (BAT)
|
|
Bit64u table_offset;
|
|
|
|
Bit32u version;
|
|
Bit32u max_table_entries; // 32bit/entry
|
|
|
|
// 2 MB by default, must be a power of two
|
|
Bit32u block_size;
|
|
|
|
Bit32u checksum;
|
|
Bit8u parent_uuid[16];
|
|
Bit32u parent_timestamp;
|
|
Bit32u reserved;
|
|
|
|
// Backing file name (in UTF-16)
|
|
Bit8u parent_name[512];
|
|
|
|
struct {
|
|
Bit32u platform;
|
|
Bit32u data_space;
|
|
Bit32u data_length;
|
|
Bit32u reserved;
|
|
Bit64u data_offset;
|
|
} parent_locator[8];
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
vhd_dyndisk_header_t;
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER<1300)
|
|
#pragma pack(pop)
|
|
#elif defined(__MWERKS__) && defined(macintosh)
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
class vpc_image_t : public device_image_t
|
|
{
|
|
public:
|
|
int open(const char* pathname, int flags);
|
|
void close();
|
|
Bit64s lseek(Bit64s offset, int whence);
|
|
ssize_t read(void* buf, size_t count);
|
|
ssize_t write(const void* buf, size_t count);
|
|
|
|
Bit32u get_capabilities();
|
|
static int check_format(int fd, Bit64u imgsize);
|
|
|
|
#ifdef BXIMAGE
|
|
int create_image(const char *pathname, Bit64u size);
|
|
#else
|
|
bool save_state(const char *backup_fname);
|
|
void restore_state(const char *backup_fname);
|
|
#endif
|
|
|
|
private:
|
|
Bit64s get_sector_offset(Bit64s sector_num, int write);
|
|
int rewrite_footer(void);
|
|
Bit64s alloc_block(Bit64s sector_num);
|
|
|
|
int fd;
|
|
Bit64s sector_count;
|
|
Bit64s cur_sector;
|
|
Bit8u footer_buf[HEADER_SIZE];
|
|
Bit64u free_data_block_offset;
|
|
int max_table_entries;
|
|
Bit64u bat_offset;
|
|
Bit64u last_bitmap_offset;
|
|
Bit32u *pagetable;
|
|
|
|
Bit32u block_size;
|
|
Bit32u bitmap_size;
|
|
|
|
const char *pathname;
|
|
};
|
|
|
|
#endif
|