Bochs/bochs/iodev/hdimage.h
Volker Ruppert 5014eed268 - link lowlevel cdrom support with the hdimage plugin instead of harddrv and usb_common. This fixes
duplicate log prefixes on Windows if both IDE and USB cdroms are used in plugin mode. Windows also
  requires the cdrom base class and the init_cdrom() method to link and work correctly.
2011-07-17 17:23:12 +00:00

594 lines
17 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2005-2011 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BX_HDIMAGE_H
#define BX_HDIMAGE_H
// hdimage capabilities
#define HDIMAGE_READONLY 1
#define HDIMAGE_HAS_GEOMETRY 2
#define HDIMAGE_AUTO_GEOMETRY 4
// SPARSE IMAGES HEADER
#define SPARSE_HEADER_MAGIC (0x02468ace)
#define SPARSE_HEADER_VERSION 2
#define SPARSE_HEADER_V1 1
#define SPARSE_HEADER_SIZE (256) // Plenty of room for later
#define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff)
typedef struct
{
Bit32u magic;
Bit32u version;
Bit32u pagesize;
Bit32u numpages;
Bit64u disk;
Bit32u padding[58];
} sparse_header_t;
#define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image"
#define STANDARD_HEADER_V1 (0x00010000)
#define STANDARD_HEADER_VERSION (0x00020000)
#define STANDARD_HEADER_SIZE (512)
// WARNING : headers are kept in x86 (little) endianness
typedef struct
{
Bit8u magic[32];
Bit8u type[16];
Bit8u subtype[16];
Bit32u version;
Bit32u header;
} standard_header_t;
#define REDOLOG_TYPE "Redolog"
#define REDOLOG_SUBTYPE_UNDOABLE "Undoable"
#define REDOLOG_SUBTYPE_VOLATILE "Volatile"
#define REDOLOG_SUBTYPE_GROWING "Growing"
// #define REDOLOG_SUBTYPE_Z_UNDOABLE "z-Undoable"
// #define REDOLOG_SUBTYPE_Z_VOLATILE "z-Volatile"
#define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff)
#define UNDOABLE_REDOLOG_EXTENSION ".redolog"
#define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION))
#define VOLATILE_REDOLOG_EXTENSION ".XXXXXX"
#define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION))
typedef struct
{
// the fields in the header are kept in little endian
Bit32u catalog; // #entries in the catalog
Bit32u bitmap; // bitmap size in bytes
Bit32u extent; // extent size in bytes
Bit32u reserved; // for data alignment
Bit64u disk; // disk size in bytes
} redolog_specific_header_t;
typedef struct
{
// the fields in the header are kept in little endian
Bit32u catalog; // #entries in the catalog
Bit32u bitmap; // bitmap size in bytes
Bit32u extent; // extent size in bytes
Bit64u disk; // disk size in bytes
} redolog_specific_header_v1_t;
typedef struct
{
standard_header_t standard;
redolog_specific_header_t specific;
Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))];
} redolog_header_t;
typedef struct
{
standard_header_t standard;
redolog_specific_header_v1_t specific;
Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_v1_t))];
} redolog_header_v1_t;
// htod : convert host to disk (little) endianness
// dtoh : convert disk (little) to host endianness
#if defined (BX_LITTLE_ENDIAN)
#define htod32(val) (val)
#define dtoh32(val) (val)
#define htod64(val) (val)
#define dtoh64(val) (val)
#else
#define htod32(val) ( (((val)&0xff000000)>>24) | (((val)&0xff0000)>>8) | (((val)&0xff00)<<8) | (((val)&0xff)<<24) )
#define dtoh32(val) htod32(val)
#define htod64(val) ( (((val)&0xff00000000000000LL)>>56) | (((val)&0xff000000000000LL)>>40) | (((val)&0xff0000000000LL)>>24) | (((val)&0xff00000000LL)>>8) | (((val)&0xff000000LL)<<8) | (((val)&0xff0000LL)<<24) | (((val)&0xff00LL)<<40) | (((val)&0xffLL)<<56) )
#define dtoh64(val) htod64(val)
#endif
#ifndef HDIMAGE_HEADERS_ONLY
class device_image_t
{
public:
// Default constructor
device_image_t();
virtual ~device_image_t() {}
// Open a image. Returns non-negative if successful.
virtual int open(const char* pathname) = 0;
// Close the image.
virtual void close() = 0;
// Position ourselves. Return the resulting offset from the
// beginning of the file.
virtual Bit64s lseek(Bit64s offset, int whence) = 0;
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
virtual ssize_t read(void* buf, size_t count) = 0;
// Write count bytes from buf. Return the number of bytes
// written (count).
virtual ssize_t write(const void* buf, size_t count) = 0;
// Get image capabilities
virtual Bit32u get_capabilities();
unsigned cylinders;
unsigned heads;
unsigned sectors;
Bit64u hd_size;
};
// FLAT MODE
class default_image_t : public device_image_t
{
public:
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Open an image with specific flags. Returns non-negative if successful.
int open(const char* pathname, int flags);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
int fd;
};
// CONCAT MODE
class concat_image_t : public device_image_t
{
public:
// Default constructor
concat_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
#define BX_CONCAT_MAX_IMAGES 8
int fd_table[BX_CONCAT_MAX_IMAGES];
Bit64s start_offset_table[BX_CONCAT_MAX_IMAGES];
Bit64s length_table[BX_CONCAT_MAX_IMAGES];
void increment_string(char *str);
int maxfd; // number of entries in tables that are valid
// notice if anyone does sequential read or write without seek in between.
// This can be supported pretty easily, but needs additional checks.
// 0=something other than seek was last operation
// 1=seek was last operation
int seek_was_last_op;
// the following variables tell which partial image file to use for
// the next read and write.
int index; // index into table
int fd; // fd to use for reads and writes
Bit64s thismin, thismax; // byte offset boundary of this image
};
// SPARSE MODE
class sparse_image_t : public device_image_t
{
// Format of a sparse file:
// 256 byte header, containing details such as page size and number of pages
// Page indirection table, mapping virtual pages to physical pages within file
// Physical pages till end of file
public:
// Default constructor
sparse_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
int fd;
#ifdef _POSIX_MAPPED_FILES
void * mmap_header;
size_t mmap_length;
size_t system_pagesize_mask;
#endif
Bit32u * pagetable;
// Header is written to disk in little-endian (x86) format
// Thus needs to be converted on big-endian systems before read
// The pagetable is also kept little endian
sparse_header_t header;
Bit32u pagesize;
int pagesize_shift;
Bit32u pagesize_mask;
Bit64s data_start;
Bit64s underlying_filesize;
char * pathname;
Bit64s position;
Bit32u position_virtual_page;
Bit32u position_physical_page;
Bit32u position_page_offset;
Bit64s underlying_current_filepos;
Bit64s total_size;
void panic(const char * message);
Bit64s get_physical_offset();
void set_virtual_page(Bit32u new_virtual_page);
void read_header();
ssize_t read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf);
sparse_image_t * parent_image;
};
#if EXTERNAL_DISK_SIMULATOR
#include "external-disk-simulator.h"
#endif
#if DLL_HD_SUPPORT
class dll_image_t : public device_image_t
{
public:
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
int vunit,vblk;
};
#endif
// REDOLOG class
class redolog_t
{
public:
redolog_t();
int make_header(const char* type, Bit64u size);
int create(const char* filename, const char* type, Bit64u size);
int create(int filedes, const char* type, Bit64u size);
int open(const char* filename, const char* type);
void close();
Bit64u get_size();
Bit64s lseek(Bit64s offset, int whence);
ssize_t read(void* buf, size_t count);
ssize_t write(const void* buf, size_t count);
private:
void print_header();
int fd;
redolog_header_t header; // Header is kept in x86 (little) endianness
Bit32u *catalog;
Bit8u *bitmap;
Bit32u extent_index;
Bit32u extent_offset;
Bit32u extent_next;
Bit32u bitmap_blocks;
Bit32u extent_blocks;
Bit64s imagepos;
};
// GROWING MODE
class growing_image_t : public device_image_t
{
public:
// Contructor
growing_image_t();
virtual ~growing_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
redolog_t *redolog;
};
// UNDOABLE MODE
class undoable_image_t : public device_image_t
{
public:
// Contructor
undoable_image_t(const char* redolog_name);
virtual ~undoable_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
redolog_t *redolog; // Redolog instance
default_image_t *ro_disk; // Read-only flat disk instance
char *redolog_name; // Redolog name
};
// VOLATILE MODE
class volatile_image_t : public device_image_t
{
public:
// Contructor
volatile_image_t(const char* redolog_name);
virtual ~volatile_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
redolog_t *redolog; // Redolog instance
default_image_t *ro_disk; // Read-only flat disk instance
char *redolog_name; // Redolog name
char *redolog_temp; // Redolog temporary file name
};
#if BX_COMPRESSED_HD_SUPPORT
#include <zlib.h>
// Default compressed READ-ONLY image class
class z_ro_image_t : public device_image_t
{
public:
// Contructor
z_ro_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
Bit64s offset;
int fd;
gzFile gzfile;
};
// Z-UNDOABLE MODE
class z_undoable_image_t : public device_image_t
{
public:
// Contructor
z_undoable_image_t(Bit64u size, const char* redolog_name);
virtual ~z_undoable_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
redolog_t *redolog; // Redolog instance
z_ro_image_t *ro_disk; // Read-only compressed flat disk instance
Bit64u size;
char *redolog_name; // Redolog name
};
// Z-VOLATILE MODE
class z_volatile_image_t : public device_image_t
{
public:
// Contructor
z_volatile_image_t(Bit64u size, const char* redolog_name);
virtual ~z_volatile_image_t();
// Open a image. Returns non-negative if successful.
int open(const char* pathname);
// Close the image.
void close();
// Position ourselves. Return the resulting offset from the
// beginning of the file.
Bit64s lseek(Bit64s offset, int whence);
// Read count bytes to the buffer buf. Return the number of
// bytes read (count).
ssize_t read(void* buf, size_t count);
// Write count bytes from buf. Return the number of bytes
// written (count).
ssize_t write(const void* buf, size_t count);
private:
redolog_t *redolog; // Redolog instance
z_ro_image_t *ro_disk; // Read-only compressed flat disk instance
Bit64u size;
char *redolog_name; // Redolog name
char *redolog_temp; // Redolog temporary file name
};
#endif
class bx_hdimage_ctl_c : public bx_hdimage_ctl_stub_c {
public:
bx_hdimage_ctl_c();
virtual ~bx_hdimage_ctl_c() {}
virtual device_image_t *init_image(Bit8u image_mode, Bit64u disk_size, const char *journal);
#ifdef LOWLEVEL_CDROM
virtual LOWLEVEL_CDROM* init_cdrom(const char *dev);
#endif
};
#endif // HDIMAGE_HEADERS_ONLY
#endif