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:
parent
080ceb8293
commit
3e54ff2e36
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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@$@
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -537,6 +537,7 @@ const char *hdimage_mode_names[] = {
|
||||
"volatile",
|
||||
"vvfat",
|
||||
"vpc",
|
||||
"vbox",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 \
|
||||
|
@ -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
420
bochs/iodev/hdimage/vbox.cc
Normal 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
121
bochs/iodev/hdimage/vbox.h
Normal 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
|
@ -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[];
|
||||
|
Loading…
Reference in New Issue
Block a user