aboutsummaryrefslogtreecommitdiff
path: root/block-bochs.c
diff options
context:
space:
mode:
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-01-05 18:56:04 +0000
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>2007-01-05 18:56:04 +0000
commit6850dd945ea7eb0beedb25435bf2bc16741aec38 (patch)
treea0c9f97380941fe826d936ae954223a08c4075b9 /block-bochs.c
parentb92090309e5ff7154e4c131438ee2d540e233955 (diff)
Support for Bochs "growing" images, by Volker Ruppert.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2296 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'block-bochs.c')
-rw-r--r--block-bochs.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/block-bochs.c b/block-bochs.c
index febb4d3fd6..35e2a6cf01 100644
--- a/block-bochs.c
+++ b/block-bochs.c
@@ -28,7 +28,8 @@
/**************************************************************/
#define HEADER_MAGIC "Bochs Virtual HD Image"
-#define HEADER_VERSION 0x00010000
+#define HEADER_VERSION 0x00020000
+#define HEADER_V1 0x00010000
#define HEADER_SIZE 512
#define REDOLOG_TYPE "Redolog"
@@ -37,7 +38,7 @@
// not allocated: 0xffffffff
// always little-endian
-struct bochs_header {
+struct bochs_header_v1 {
char magic[32]; // "Bochs Virtual HD Image"
char type[16]; // "Redolog"
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
@@ -56,6 +57,27 @@ struct bochs_header {
} extra;
};
+// always little-endian
+struct bochs_header {
+ char magic[32]; // "Bochs Virtual HD Image"
+ char type[16]; // "Redolog"
+ char subtype[16]; // "Undoable" / "Volatile" / "Growing"
+ uint32_t version;
+ uint32_t header; // size of header
+
+ union {
+ struct {
+ uint32_t catalog; // num of entries
+ uint32_t bitmap; // bitmap size
+ uint32_t extent; // extent size
+ uint32_t reserved; // for ???
+ uint64_t disk; // disk size
+ char padding[HEADER_SIZE - 64 - 8 - 24];
+ } redolog;
+ char padding[HEADER_SIZE - 64 - 8];
+ } extra;
+};
+
typedef struct BDRVBochsState {
int fd;
@@ -79,7 +101,8 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
if (!strcmp(bochs->magic, HEADER_MAGIC) &&
!strcmp(bochs->type, REDOLOG_TYPE) &&
!strcmp(bochs->subtype, GROWING_TYPE) &&
- (le32_to_cpu(bochs->version) == HEADER_VERSION))
+ ((le32_to_cpu(bochs->version) == HEADER_VERSION) ||
+ (le32_to_cpu(bochs->version) == HEADER_V1)))
return 100;
return 0;
@@ -90,6 +113,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
BDRVBochsState *s = bs->opaque;
int fd, i;
struct bochs_header bochs;
+ struct bochs_header_v1 header_v1;
fd = open(filename, O_RDWR | O_BINARY);
if (fd < 0) {
@@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
if (strcmp(bochs.magic, HEADER_MAGIC) ||
strcmp(bochs.type, REDOLOG_TYPE) ||
strcmp(bochs.subtype, GROWING_TYPE) ||
- (le32_to_cpu(bochs.version) != HEADER_VERSION)) {
+ ((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
+ (le32_to_cpu(bochs.version) != HEADER_V1))) {
goto fail;
}
- bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
+ if (le32_to_cpu(bochs.version) == HEADER_V1) {
+ memcpy(&header_v1, &bochs, sizeof(bochs));
+ bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
+ } else {
+ bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
+ }
lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);