Added Oracle(tm) VM VirtualBox image support (VDI version 1.1). Patch written

by Ben Lunt plus some additions (bximage fixes, big endian support).
TODO: update MSVC workspace files.
This commit is contained in:
Volker Ruppert 2015-03-29 14:27:32 +00:00
parent 080ceb8293
commit 3e54ff2e36
12 changed files with 593 additions and 15 deletions

View File

@ -666,7 +666,8 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
# This defines the type and characteristics of all attached ata devices:
# type= type of attached device [disk|cdrom]
# mode= only valid for disks [flat|concat|external|dll|sparse|vmware3]
# [vmware4|undoable|growing|volatile|vpc|vvfat]
# [vmware4|undoable|growing|volatile|vpc]
# [vbox|vvfat]
# path= path of the image / directory
# cylinders= only valid for disks
# heads= only valid for disks

View File

@ -25,6 +25,7 @@ Changes after 2.6.7 release:
- I/O Devices
- Hard drive
- Re-enable "bulk I/O" repeat speedups extension.
- Added Oracle(tm) VM VirtualBox image support (VDI version 1.1)
- Sound
- SB16: Fixed OPL chip detection by implementing ISA bus delay.
- SB16: Ported OPL3 emulation from DOSBox and partly removed legacy code.

View File

@ -247,8 +247,8 @@ bochs_plugins:
$(MAKE) plugins
@CD_UP_TWO@
bximage@EXE@: misc/bximage.o misc/hdimage.o misc/vmware3.o misc/vmware4.o misc/vpc-img.o
@LINK_CONSOLE@ $(BXIMAGE_LINK_OPTS) misc/bximage.o misc/hdimage.o misc/vmware3.o misc/vmware4.o misc/vpc-img.o
bximage@EXE@: misc/bximage.o misc/hdimage.o misc/vmware3.o misc/vmware4.o misc/vpc-img.o misc/vbox.o
@LINK_CONSOLE@ $(BXIMAGE_LINK_OPTS) misc/bximage.o misc/hdimage.o misc/vmware3.o misc/vmware4.o misc/vpc-img.o misc/vbox.o
niclist@EXE@: misc/niclist.o
@LINK_CONSOLE@ misc/niclist.o
@ -274,6 +274,10 @@ misc/vpc-img.o: $(srcdir)/iodev/hdimage/vpc-img.cc $(srcdir)/iodev/hdimage/vpc-i
$(srcdir)/iodev/hdimage/hdimage.h $(srcdir)/misc/bxcompat.h
$(CXX) @DASH@c $(BX_INCDIRS) @BXIMAGE_FLAG@ $(CXXFLAGS_CONSOLE) $(srcdir)/iodev/hdimage/vpc-img.cc @OFP@$@
misc/vbox.o: $(srcdir)/iodev/hdimage/vbox.cc $(srcdir)/iodev/hdimage/vbox.h \
$(srcdir)/iodev/hdimage/hdimage.h $(srcdir)/misc/bxcompat.h
$(CXX) @DASH@c $(BX_INCDIRS) @BXIMAGE_FLAG@ $(CXXFLAGS_CONSOLE) $(srcdir)/iodev/hdimage/vbox.cc @OFP@$@
# compile with console CFLAGS, not gui CXXFLAGS
misc/niclist.o: $(srcdir)/misc/niclist.c
$(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS_CONSOLE) $(srcdir)/misc/niclist.c @OFP@$@

View File

@ -4047,7 +4047,7 @@ This defines the type and characteristics of all attached ata devices:
<row>
<entry> mode </entry>
<entry> image type, only valid for disks </entry>
<entry> [flat | concat | external | dll | sparse | vmware3 | vmware4 | undoable | growing | volatile | vpc | vvfat ]</entry>
<entry> [flat | concat | external | dll | sparse | vmware3 | vmware4 | undoable | growing | volatile | vpc | vbox | vvfat ]</entry>
</row>
<row> <entry> cylinders </entry> <entry> only valid for disks </entry> </row>
<row> <entry> heads </entry> <entry> only valid for disks </entry> </row>
@ -4151,6 +4151,9 @@ volatile : read-only base file with volatile redolog
vpc: fixed / dynamic size VirtualPC image
</para></listitem>
<listitem><para>
vbox: fixed / dynamic size Oracle(tm) VM VirtualBox image (VDI version 1.1)
</para></listitem>
<listitem><para>
vvfat: local directory appears as VFAT disk (with volatile redolog / optional commit)
</para></listitem>
</itemizedlist>
@ -8555,6 +8558,11 @@ If unspecified, the default "mode" is flat.
fixed / dynamic size supported
</entry>
</row>
<row> <entry> vbox </entry> <entry> Oracle(tm) VM VirtualBox disk support </entry>
<entry>
VDI version 1.1 fixed / dynamic size supported
</entry>
</row>
<row> <entry> vvfat </entry> <entry> local directory appears as VFAT disk (with volatile redolog) </entry>
<entry>
optional commit or rollback

View File

@ -1,5 +1,5 @@
.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com"
.TH bochsrc 5 "15 Nov 2014" "bochsrc" "The Bochs Project"
.TH bochsrc 5 "29 Mar 2015" "bochsrc" "The Bochs Project"
.\"SKIP_SECTION"
.SH NAME
bochsrc \- Configuration file for Bochs.
@ -709,7 +709,7 @@ Examples:
This defines the type and characteristics of all attached ata devices:
type= type of attached device [disk|cdrom]
path= path of the image
mode= image mode [flat|concat|external|dll|sparse|vmware3|vmware4|undoable|growing|volatile|vpc|vvfat], only valid for disks
mode= image mode [flat|concat|external|dll|sparse|vmware3|vmware4|undoable|growing|volatile|vpc|vbox|vvfat], only valid for disks
cylinders= only valid for disks
heads= only valid for disks
spt= only valid for disks
@ -746,6 +746,7 @@ The mode option defines how the disk image is handled. Disks can be defined as:
- growing : growing file
- volatile : flat file with volatile redolog
- vpc : fixed / dynamic size VirtualPC image
- vbox : fixed / dynamic size Oracle(tm) VM VirtualBox image (VDI version 1.1)
- vvfat: local directory appears as read-only VFAT disk (with volatile redolog)
The disk translation scheme (implemented in legacy int13 bios functions, and used by

View File

@ -537,6 +537,7 @@ const char *hdimage_mode_names[] = {
"volatile",
"vvfat",
"vpc",
"vbox",
NULL
};

View File

@ -546,9 +546,10 @@ enum {
BX_HDIMAGE_MODE_GROWING,
BX_HDIMAGE_MODE_VOLATILE,
BX_HDIMAGE_MODE_VVFAT,
BX_HDIMAGE_MODE_VPC
BX_HDIMAGE_MODE_VPC,
BX_HDIMAGE_MODE_VBOX
};
#define BX_HDIMAGE_MODE_LAST BX_HDIMAGE_MODE_VPC
#define BX_HDIMAGE_MODE_LAST BX_HDIMAGE_MODE_VBOX
#define BX_HDIMAGE_MODE_UNKNOWN -1
enum {

View File

@ -50,7 +50,7 @@ LIBTOOL=@LIBTOOL@
WIN32_DLL_IMPORT_LIBRARY=../../@WIN32_DLL_IMPORT_LIB@
CDROM_OBJS = @CDROM_OBJS@
HDIMAGE_EXTRA_OBJS = vmware3.o vmware4.o vpc-img.o vvfat.o
HDIMAGE_EXTRA_OBJS = vmware3.o vmware4.o vbox.o vpc-img.o vvfat.o
HDIMAGE_LINK_OPTS =
HDIMAGE_LINK_OPTS_VCPP = user32.lib
@ -93,8 +93,8 @@ libbx_%.la: %.lo
$(LIBTOOL) --mode=link --tag CXX $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH)
# special link rules for plugins that require more than one object file
libbx_hdimage.la: hdimage.lo vmware3.lo vmware4.lo vvfat.lo vpc-img.lo $(CDROM_OBJS:.o=.lo)
$(LIBTOOL) --mode=link --tag CXX $(CXX) -module hdimage.lo vmware3.lo vmware4.lo vvfat.lo vpc-img.lo $(CDROM_OBJS:.o=.lo) -o libbx_hdimage.la -rpath $(PLUGIN_PATH)
libbx_hdimage.la: hdimage.lo $(HDIMAGE_EXTRA_OBJS:.o=.lo) $(CDROM_OBJS:.o=.lo)
$(LIBTOOL) --mode=link --tag CXX $(CXX) -module hdimage.lo $(HDIMAGE_EXTRA_OBJS:.o=.lo) $(CDROM_OBJS:.o=.lo) -o libbx_hdimage.la -rpath $(PLUGIN_PATH)
#### building DLLs for win32 (Cygwin and MinGW/MSYS)
bx_%.dll: %.o
@ -154,7 +154,13 @@ hdimage.o: hdimage.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \
../../memory/memory.h ../../pc_system.h ../../gui/gui.h \
../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \
../../param_names.h cdrom.h cdrom_amigaos.h cdrom_misc.h cdrom_osx.h \
cdrom_win32.h hdimage.h vmware3.h vmware4.h vvfat.h vpc-img.h
cdrom_win32.h hdimage.h vmware3.h vmware4.h vvfat.h vpc-img.h vbox.h
vbox.o: vbox.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \
../../bx_debug/debug.h ../../config.h ../../osdep.h \
../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \
../../memory/memory.h ../../pc_system.h ../../gui/gui.h \
../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \
../../param_names.h hdimage.h vbox.h
vmware3.o: vmware3.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \
../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \
../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \
@ -211,7 +217,13 @@ hdimage.lo: hdimage.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \
../../memory/memory.h ../../pc_system.h ../../gui/gui.h \
../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \
../../param_names.h cdrom.h cdrom_amigaos.h cdrom_misc.h cdrom_osx.h \
cdrom_win32.h hdimage.h vmware3.h vmware4.h vvfat.h vpc-img.h
cdrom_win32.h hdimage.h vmware3.h vmware4.h vvfat.h vpc-img.h vbox.h
vbox.lo: vbox.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \
../../bx_debug/debug.h ../../config.h ../../osdep.h \
../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \
../../memory/memory.h ../../pc_system.h ../../gui/gui.h \
../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \
../../param_names.h hdimage.h vbox.h
vmware3.lo: vmware3.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \
../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \
../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \

View File

@ -42,6 +42,7 @@
#include "vmware4.h"
#include "vvfat.h"
#include "vpc-img.h"
#include "vbox.h"
#if BX_HAVE_SYS_MMAN_H
#include <sys/mman.h>
@ -138,6 +139,10 @@ device_image_t* bx_hdimage_ctl_c::init_image(Bit8u image_mode, Bit64u disk_size,
hdimage = new vpc_image_t();
break;
case BX_HDIMAGE_MODE_VBOX:
hdimage = new vbox_image_t();
break;
default:
BX_PANIC(("unsupported HD mode : '%s'", hdimage_mode_names[image_mode]));
break;
@ -254,6 +259,8 @@ int hdimage_detect_image_mode(const char *pathname)
result = BX_HDIMAGE_MODE_GROWING;
} else if (vpc_image_t::check_format(fd, image_size) >= HDIMAGE_FORMAT_OK) {
result = BX_HDIMAGE_MODE_VPC;
} else if (vbox_image_t::check_format(fd, image_size) >= HDIMAGE_FORMAT_OK) {
result = BX_HDIMAGE_MODE_VBOX;
} else if (flat_image_t::check_format(fd, image_size) == HDIMAGE_FORMAT_OK) {
result = BX_HDIMAGE_MODE_FLAT;
}

420
bochs/iodev/hdimage/vbox.cc Normal file
View File

@ -0,0 +1,420 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
/*
* This file provides support for the following VBox virtual
* disk image formats: VDI.
*
* Author: Benjamin D Lunt
* Contact: fys [at] fysnet [dot] net
*
* Copyright (C) 2015 Benjamin D Lunt.
* Copyright (C) 2006-2015 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.1 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
*
* Information found at:
* https://forums.virtualbox.org/viewtopic.php?t=8046
*
* Many Image Files can be found at:
* http://sourceforge.net/projects/virtualboximage/files/
*
*/
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#ifdef BXIMAGE
#include "config.h"
#include "misc/bxcompat.h"
#include "misc/bswap.h"
#include "osdep.h"
#else
#include "iodev.h"
#endif
#include "hdimage.h"
#include "vbox.h"
#define LOG_THIS bx_devices.pluginHDImageCtl->
const off_t vbox_image_t::INVALID_OFFSET = (off_t)-1;
const int vbox_image_t::SECTOR_SIZE = 512;
vbox_image_t::vbox_image_t()
: file_descriptor(-1),
mtlb(0),
block_data(0),
current_offset(INVALID_OFFSET),
mtlb_sector(0),
is_dirty(0),
mtlb_dirty(0),
header_dirty(0)
{
if (sizeof(_VBOX_VDI_Header) != 512) {
BX_PANIC(("system error: invalid header structure size"));
}
}
vbox_image_t::~vbox_image_t()
{
close();
}
int vbox_image_t::open(const char* _pathname, int flags)
{
Bit64u imgsize = 0;
pathname = _pathname;
close();
file_descriptor = hdimage_open_file(pathname, flags, &imgsize, &mtime);
if (!is_open())
return -1;
if (!read_header()) {
BX_PANIC(("unable to read vbox virtual disk header from file '%s'", pathname));
return -1;
}
// allocate one block of memory
block_data = new Bit8u[(unsigned) header.block_size];
if (block_data == 0) {
BX_PANIC(("unable to allocate %d bytes for vbox block size", header.block_size));
}
is_dirty = 0;
mtlb_dirty = 0;
header_dirty = 0;
// we allocate and read the image block map.
// it is not a very large size, since each entry is only 32-bits and
// a 10-gig image will only use 40k of memory in this block.
// (10gig = 10240 1-meg blocks with each entry using 4 bytes) = 40k
mtlb = new Bit32s[(unsigned) header.blocks_in_hdd];
if (mtlb == 0) {
BX_PANIC(("unable to allocate %lu bytes for vbox image's map table", header.blocks_in_hdd * sizeof(Bit32u)));
}
// read in the map table
if (bx_read_image(file_descriptor, header.offset_blocks, mtlb, (unsigned) header.blocks_in_hdd * sizeof(Bit32u))
!= (ssize_t)(header.blocks_in_hdd * sizeof(Bit32u))) {
BX_PANIC(("did not read in map table"));
}
// read in the first index so that we have something in memory
read_block(0);
mtlb_sector = 0;
current_offset = 0;
hd_size = header.disk_size;
if ((unsigned) header.cylinders > 0) {
cylinders = (unsigned) header.cylinders;
heads = (unsigned) header.heads;
spt = (unsigned) header.sectors;
} else {
cylinders = (unsigned) ((header.disk_size / 512) / 16) / 63;
heads = 16;
spt = 63;
}
BX_DEBUG(("VBox VDI disk geometry:"));
BX_DEBUG((" .size = " FMT_LL "d", hd_size));
BX_DEBUG((" .cylinders = %d", cylinders));
BX_DEBUG((" .heads = %d", heads));
BX_DEBUG((" .sectors = %d", spt));
return 1;
}
void vbox_image_t::close()
{
if (file_descriptor == -1)
return;
flush();
// write the map back to the disk
if (mtlb_dirty) {
if (bx_write_image(file_descriptor, header.offset_blocks, mtlb, (unsigned) header.blocks_in_hdd * sizeof(Bit32u))
!= (ssize_t)(header.blocks_in_hdd * sizeof(Bit32u))) {
BX_PANIC(("did not write map table"));
}
}
// write header back to image
if (header_dirty) {
if (bx_write_image(file_descriptor, 0, &header, sizeof(VBOX_VDI_Header)) != sizeof(VBOX_VDI_Header)) {
BX_PANIC(("did not write header"));
}
}
delete [] mtlb; mtlb = 0;
delete [] block_data; block_data = 0;
::close(file_descriptor);
file_descriptor = -1;
}
Bit64s vbox_image_t::lseek(Bit64s offset, int whence)
{
switch (whence) {
case SEEK_SET:
current_offset = (off_t) offset;
return current_offset;
case SEEK_CUR:
current_offset += (off_t) offset;
return current_offset;
case SEEK_END:
current_offset = header.disk_size + (off_t)offset;
return current_offset;
default:
BX_INFO(("unknown 'whence' value (%d) when trying to seek vbox image", whence));
return INVALID_OFFSET;
}
}
ssize_t vbox_image_t::read(void *buf, size_t count)
{
ssize_t total = 0;
while (count > 0) {
off_t readable = perform_seek();
if (readable == INVALID_OFFSET) {
BX_ERROR(("vbox disk image read failed on %u bytes at " FMT_LL "d", (unsigned)count, current_offset));
return -1;
}
off_t copysize = ((off_t)count > readable) ? readable : count;
off_t offset = current_offset & (header.block_size - 1);
memcpy(buf, block_data + (size_t) offset, (size_t) copysize);
current_offset += copysize;
total += (long) copysize;
count -= (size_t) copysize;
}
return total;
}
ssize_t vbox_image_t::write(const void *buf, size_t count)
{
ssize_t total = 0;
while (count > 0) {
off_t writable = perform_seek();
if (writable == INVALID_OFFSET) {
BX_ERROR(("vbox disk image write failed on %u bytes at " FMT_LL "d", (unsigned)count, current_offset));
return -1;
}
off_t writesize = ((off_t)count > writable) ? writable : count;
off_t offset = current_offset & (header.block_size - 1);
memcpy(block_data + offset, buf, (size_t) writesize);
current_offset += writesize;
total += (long) writesize;
count -= (size_t) writesize;
is_dirty = 1;
}
return total;
}
int vbox_image_t::check_format(int fd, Bit64u imgsize)
{
VBOX_VDI_Header temp_header;
if (bx_read_image(fd, 0, &temp_header, sizeof(VBOX_VDI_Header)) != sizeof(VBOX_VDI_Header))
return HDIMAGE_READ_ERROR;
// type can be 1 (Dynamic) or 2 (Static/Fixed)
// block size must be 1Meg (FIXME: I think it can be anything as long as it is a power of 2)
// sector size must be 512
if (((temp_header.image_type < 1) || (temp_header.image_type > 2))
|| (temp_header.block_size != 0x00100000)
|| (temp_header.sector_size != 0x00000200))
return HDIMAGE_NO_SIGNATURE;
// version must be 01.01
if (temp_header.version != 0x00010001)
return HDIMAGE_VERSION_ERROR;
return HDIMAGE_FORMAT_OK;
}
bx_bool vbox_image_t::is_open() const
{
return (file_descriptor != -1);
}
bx_bool vbox_image_t::read_header()
{
int ret;
if (!is_open())
BX_PANIC(("attempt to read vbox header from a closed file"));
if ((ret = check_format(file_descriptor, 0)) != HDIMAGE_FORMAT_OK) {
switch (ret) {
case HDIMAGE_READ_ERROR:
BX_ERROR(("vbox image read error"));
break;
case HDIMAGE_NO_SIGNATURE:
BX_ERROR(("not a vbox image"));
break;
case HDIMAGE_VERSION_ERROR:
BX_ERROR(("unsupported vbox image version"));
break;
}
return 0;
}
if (bx_read_image(file_descriptor, 0, &header, sizeof(VBOX_VDI_Header)) != sizeof(VBOX_VDI_Header)) {
return 0;
}
BX_DEBUG(("VBOX_VDI_Header (size=%u)", (unsigned)sizeof(VBOX_VDI_Header)));
BX_DEBUG((" .version = %08X", header.version));
BX_DEBUG((" .flags = %08X", header.flags));
BX_DEBUG((" .disk_size = " FMT_LL "d", header.disk_size));
BX_DEBUG((" .type = %d (%s)", header.image_type, (header.image_type == 1) ? "Dynamic" : "Static"));
return 1;
}
//
// Returns the number of bytes that can be read from the current offset before needing
// to perform another seek.
//
off_t vbox_image_t::perform_seek()
{
if (current_offset == INVALID_OFFSET) {
BX_ERROR(("invalid offset specified in vbox seek"));
return INVALID_OFFSET;
}
Bit32u index = (Bit32u) (current_offset / header.block_size);
if (mtlb_sector == index) {
return header.block_size - (current_offset & (header.block_size - 1));
} else {
flush();
read_block(index);
mtlb_sector = index;
return header.block_size;
}
}
void vbox_image_t::flush()
{
if (!is_dirty)
return;
//
// Write dirty sectors to disk.
//
write_block(mtlb_sector);
is_dirty = 0;
}
void vbox_image_t::read_block(const Bit32u index)
{
off_t offset;
// if the mtlb[index] returns -1, then we haven't written this sector
// to disk yet, so return an "empty" buffer
if (dtoh32(mtlb[index]) == -1) {
if (header.image_type == 2) {
BX_PANIC(("Found non-existing block in Static type image"));
}
memset(block_data, 0, header.block_size);
BX_DEBUG(("reading empty block index %d", index));
} else {
if (dtoh32(mtlb[index]) >= (int) header.blocks_in_hdd) {
BX_PANIC(("Trying to read past end of image (index out of range)"));
}
offset = dtoh32(mtlb[index]) * header.block_size;
bx_read_image(file_descriptor, header.offset_data + offset, block_data, header.block_size);
BX_DEBUG(("reading block index %d (%d) " FMT_LL "d", index, dtoh32(mtlb[index]), offset));
}
}
void vbox_image_t::write_block(const Bit32u index)
{
off_t offset;
// if the mtlb[index] returns -1, then we haven't written this sector
// to disk yet, so allocate another and write it to file
if (dtoh32(mtlb[index]) == -1) {
if (header.image_type == 2) {
BX_PANIC(("Found non-existing block in Static type image"));
}
mtlb[index] = htod32(header.blocks_allocated++);
BX_DEBUG(("allocating new block at block: %d", dtoh32(mtlb[index])));
mtlb_dirty = 1;
header_dirty = 1;
}
if (dtoh32(mtlb[index]) >= (int) header.blocks_in_hdd) {
BX_PANIC(("Trying to write past end of image (index out of range)"));
}
offset = dtoh32(mtlb[index]) * header.block_size;
BX_DEBUG(("writing block index %d (%d) " FMT_LL "d", index, dtoh32(mtlb[index]), offset));
bx_write_image(file_descriptor, header.offset_data + offset, block_data, header.block_size);
}
Bit32u vbox_image_t::get_capabilities(void)
{
return HDIMAGE_HAS_GEOMETRY;
}
#ifndef BXIMAGE
bx_bool vbox_image_t::save_state(const char *backup_fname)
{
return hdimage_backup_file(file_descriptor, backup_fname);
}
void vbox_image_t::restore_state(const char *backup_fname)
{
int temp_fd;
Bit64u imgsize;
if ((temp_fd = hdimage_open_file(backup_fname, O_RDONLY, &imgsize, NULL)) < 0) {
BX_PANIC(("Cannot open vbox image backup '%s'", backup_fname));
return;
}
if (check_format(temp_fd, imgsize) < HDIMAGE_FORMAT_OK) {
::close(temp_fd);
BX_PANIC(("Cannot detect vbox image header"));
return;
}
::close(temp_fd);
close();
if (!hdimage_copy_file(backup_fname, pathname)) {
BX_PANIC(("Failed to restore vbox image '%s'", pathname));
return;
}
device_image_t::open(pathname);
}
#endif

121
bochs/iodev/hdimage/vbox.h Normal file
View File

@ -0,0 +1,121 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
/*
* This file provides support for the following VBox virtual
* disk image formats: VDI.
*
* Author: Benjamin D Lunt
* Contact: fys [at] fysnet [dot] net
*
* Copyright (C) 2015 Benjamin D Lunt.
* Copyright (C) 2006-2015 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.1 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 _VBOX_H
#define _VBOX_H 1
#if defined(_MSC_VER)
#pragma pack(push, 1)
#elif defined(__MWERKS__) && defined(macintosh)
#pragma options align=packed
#endif
typedef struct _VBOX_VDI_Header
{
Bit8u id[64]; // "<<< Sun xVM VirtualBox Disk Image >>>" + LF + Padding NULLs
Bit32u signature; // image signature
Bit32u version; // version (max.min) (two 16-bit words)
Bit32u header_size; // size of header (0x190 ?)
Bit32u image_type; // image type (1 = Dynamic VDI, 2 = Static VDI)
Bit32u flags; // image flags
Bit8u description[256]; // image description
Bit32u offset_blocks; // byte offset to mapped area
Bit32u offset_data; // byte offset to data area (actual data blocks)
Bit32u cylinders; // number of cylinders
Bit32u heads; // number of heads
Bit32u sectors; // number of sectors
Bit32u sector_size; // sector size in bytes
Bit32u resv; // unused
Bit64u disk_size; // disk size in bytes
Bit32u block_size; // block size
Bit32u block_extra; // block extra data
Bit32u blocks_in_hdd; // total number of blocks in HDD (count of entries in map)
Bit32u blocks_allocated; // number of blocks allocated
Bit8u uuid_this[16]; // UUID of this VDI
Bit8u uuid_snap[16]; // UUID of last SNAP
Bit8u uuid_link[16]; // UUID link
Bit8u uuid_parent[16]; // UUID parent
Bit8u padding[56]; // padding to end of header
}
#if !defined(_MSC_VER)
GCC_ATTRIBUTE((packed))
#endif
VBOX_VDI_Header;
#if defined(_MSC_VER)
#pragma pack(pop)
#elif defined(__MWERKS__) && defined(macintosh)
#pragma options align=reset
#endif
class vbox_image_t : public device_image_t
{
public:
vbox_image_t();
virtual ~vbox_image_t();
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);
#ifndef BXIMAGE
bx_bool save_state(const char *backup_fname);
void restore_state(const char *backup_fname);
#endif
private:
static const off_t INVALID_OFFSET;
static const int SECTOR_SIZE;
bx_bool is_open() const;
bx_bool read_header();
off_t perform_seek();
void flush();
void read_block(const Bit32u index);
void write_block(const Bit32u index);
int file_descriptor;
VBOX_VDI_Header header;
Bit32s *mtlb;
Bit8u *block_data;
off_t current_offset;
Bit32u mtlb_sector;
bx_bool is_dirty;
bx_bool mtlb_dirty;
bx_bool header_dirty;
const char *pathname;
};
#endif

View File

@ -54,9 +54,10 @@ enum {
BX_HDIMAGE_MODE_GROWING,
BX_HDIMAGE_MODE_VOLATILE,
BX_HDIMAGE_MODE_VVFAT,
BX_HDIMAGE_MODE_VPC
BX_HDIMAGE_MODE_VPC,
BX_HDIMAGE_MODE_VBOX
};
#define BX_HDIMAGE_MODE_LAST BX_HDIMAGE_MODE_VPC
#define BX_HDIMAGE_MODE_LAST BX_HDIMAGE_MODE_VBOX
#define BX_HDIMAGE_MODE_UNKNOWN -1
extern const char *hdimage_mode_names[];