Commit 6850dd945ea7eb0beedb25435bf2bc16741aec38
1 parent
b9209030
Support for Bochs "growing" images, by Volker Ruppert.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2296 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
35 additions
and
5 deletions
block-bochs.c
@@ -28,7 +28,8 @@ | @@ -28,7 +28,8 @@ | ||
28 | /**************************************************************/ | 28 | /**************************************************************/ |
29 | 29 | ||
30 | #define HEADER_MAGIC "Bochs Virtual HD Image" | 30 | #define HEADER_MAGIC "Bochs Virtual HD Image" |
31 | -#define HEADER_VERSION 0x00010000 | 31 | +#define HEADER_VERSION 0x00020000 |
32 | +#define HEADER_V1 0x00010000 | ||
32 | #define HEADER_SIZE 512 | 33 | #define HEADER_SIZE 512 |
33 | 34 | ||
34 | #define REDOLOG_TYPE "Redolog" | 35 | #define REDOLOG_TYPE "Redolog" |
@@ -37,7 +38,7 @@ | @@ -37,7 +38,7 @@ | ||
37 | // not allocated: 0xffffffff | 38 | // not allocated: 0xffffffff |
38 | 39 | ||
39 | // always little-endian | 40 | // always little-endian |
40 | -struct bochs_header { | 41 | +struct bochs_header_v1 { |
41 | char magic[32]; // "Bochs Virtual HD Image" | 42 | char magic[32]; // "Bochs Virtual HD Image" |
42 | char type[16]; // "Redolog" | 43 | char type[16]; // "Redolog" |
43 | char subtype[16]; // "Undoable" / "Volatile" / "Growing" | 44 | char subtype[16]; // "Undoable" / "Volatile" / "Growing" |
@@ -56,6 +57,27 @@ struct bochs_header { | @@ -56,6 +57,27 @@ struct bochs_header { | ||
56 | } extra; | 57 | } extra; |
57 | }; | 58 | }; |
58 | 59 | ||
60 | +// always little-endian | ||
61 | +struct bochs_header { | ||
62 | + char magic[32]; // "Bochs Virtual HD Image" | ||
63 | + char type[16]; // "Redolog" | ||
64 | + char subtype[16]; // "Undoable" / "Volatile" / "Growing" | ||
65 | + uint32_t version; | ||
66 | + uint32_t header; // size of header | ||
67 | + | ||
68 | + union { | ||
69 | + struct { | ||
70 | + uint32_t catalog; // num of entries | ||
71 | + uint32_t bitmap; // bitmap size | ||
72 | + uint32_t extent; // extent size | ||
73 | + uint32_t reserved; // for ??? | ||
74 | + uint64_t disk; // disk size | ||
75 | + char padding[HEADER_SIZE - 64 - 8 - 24]; | ||
76 | + } redolog; | ||
77 | + char padding[HEADER_SIZE - 64 - 8]; | ||
78 | + } extra; | ||
79 | +}; | ||
80 | + | ||
59 | typedef struct BDRVBochsState { | 81 | typedef struct BDRVBochsState { |
60 | int fd; | 82 | int fd; |
61 | 83 | ||
@@ -79,7 +101,8 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename) | @@ -79,7 +101,8 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename) | ||
79 | if (!strcmp(bochs->magic, HEADER_MAGIC) && | 101 | if (!strcmp(bochs->magic, HEADER_MAGIC) && |
80 | !strcmp(bochs->type, REDOLOG_TYPE) && | 102 | !strcmp(bochs->type, REDOLOG_TYPE) && |
81 | !strcmp(bochs->subtype, GROWING_TYPE) && | 103 | !strcmp(bochs->subtype, GROWING_TYPE) && |
82 | - (le32_to_cpu(bochs->version) == HEADER_VERSION)) | 104 | + ((le32_to_cpu(bochs->version) == HEADER_VERSION) || |
105 | + (le32_to_cpu(bochs->version) == HEADER_V1))) | ||
83 | return 100; | 106 | return 100; |
84 | 107 | ||
85 | return 0; | 108 | return 0; |
@@ -90,6 +113,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags) | @@ -90,6 +113,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags) | ||
90 | BDRVBochsState *s = bs->opaque; | 113 | BDRVBochsState *s = bs->opaque; |
91 | int fd, i; | 114 | int fd, i; |
92 | struct bochs_header bochs; | 115 | struct bochs_header bochs; |
116 | + struct bochs_header_v1 header_v1; | ||
93 | 117 | ||
94 | fd = open(filename, O_RDWR | O_BINARY); | 118 | fd = open(filename, O_RDWR | O_BINARY); |
95 | if (fd < 0) { | 119 | if (fd < 0) { |
@@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags) | @@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags) | ||
109 | if (strcmp(bochs.magic, HEADER_MAGIC) || | 133 | if (strcmp(bochs.magic, HEADER_MAGIC) || |
110 | strcmp(bochs.type, REDOLOG_TYPE) || | 134 | strcmp(bochs.type, REDOLOG_TYPE) || |
111 | strcmp(bochs.subtype, GROWING_TYPE) || | 135 | strcmp(bochs.subtype, GROWING_TYPE) || |
112 | - (le32_to_cpu(bochs.version) != HEADER_VERSION)) { | 136 | + ((le32_to_cpu(bochs.version) != HEADER_VERSION) && |
137 | + (le32_to_cpu(bochs.version) != HEADER_V1))) { | ||
113 | goto fail; | 138 | goto fail; |
114 | } | 139 | } |
115 | 140 | ||
116 | - bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512; | 141 | + if (le32_to_cpu(bochs.version) == HEADER_V1) { |
142 | + memcpy(&header_v1, &bochs, sizeof(bochs)); | ||
143 | + bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512; | ||
144 | + } else { | ||
145 | + bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512; | ||
146 | + } | ||
117 | 147 | ||
118 | lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET); | 148 | lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET); |
119 | 149 |