block-vpc: Write support (Kevin Wolf)
[qemu] / block-vpc.c
1 /*
2  * Block driver for Conectix/Microsoft Virtual PC images
3  *
4  * Copyright (c) 2005 Alex Beregszaszi
5  * Copyright (c) 2009 Kevin Wolf <kwolf@suse.de>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #include "qemu-common.h"
26 #include "block_int.h"
27
28 /**************************************************************/
29
30 #define HEADER_SIZE 512
31
32 //#define CACHE
33
34 enum vhd_type {
35     VHD_FIXED           = 2,
36     VHD_DYNAMIC         = 3,
37     VHD_DIFFERENCING    = 4,
38 };
39
40 // always big-endian
41 struct vhd_footer {
42     char        creator[8]; // "conectix"
43     uint32_t    features;
44     uint32_t    version;
45
46     // Offset of next header structure, 0xFFFFFFFF if none
47     uint64_t    data_offset;
48
49     // Seconds since Jan 1, 2000 0:00:00 (UTC)
50     uint32_t    timestamp;
51
52     char        creator_app[4]; // "vpc "
53     uint16_t    major;
54     uint16_t    minor;
55     char        creator_os[4]; // "Wi2k"
56
57     uint64_t    orig_size;
58     uint64_t    size;
59
60     uint16_t    cyls;
61     uint8_t     heads;
62     uint8_t     secs_per_cyl;
63
64     uint32_t    type;
65
66     // Checksum of the Hard Disk Footer ("one's complement of the sum of all
67     // the bytes in the footer without the checksum field")
68     uint32_t    checksum;
69
70     // UUID used to identify a parent hard disk (backing file)
71     uint8_t     uuid[16];
72
73     uint8_t     in_saved_state;
74 };
75
76 struct vhd_dyndisk_header {
77     char        magic[8]; // "cxsparse"
78
79     // Offset of next header structure, 0xFFFFFFFF if none
80     uint64_t    data_offset;
81
82     // Offset of the Block Allocation Table (BAT)
83     uint64_t    table_offset;
84
85     uint32_t    version;
86     uint32_t    max_table_entries; // 32bit/entry
87
88     // 2 MB by default, must be a power of two
89     uint32_t    block_size;
90
91     uint32_t    checksum;
92     uint8_t     parent_uuid[16];
93     uint32_t    parent_timestamp;
94     uint32_t    reserved;
95
96     // Backing file name (in UTF-16)
97     uint8_t     parent_name[512];
98
99     struct {
100         uint32_t    platform;
101         uint32_t    data_space;
102         uint32_t    data_length;
103         uint32_t    reserved;
104         uint64_t    data_offset;
105     } parent_locator[8];
106 };
107
108 typedef struct BDRVVPCState {
109     BlockDriverState *hd;
110
111     uint8_t footer_buf[HEADER_SIZE];
112     uint64_t free_data_block_offset;
113     int max_table_entries;
114     uint32_t *pagetable;
115     uint64_t bat_offset;
116     uint64_t last_bitmap_offset;
117
118     uint32_t block_size;
119     uint32_t bitmap_size;
120
121 #ifdef CACHE
122     uint8_t *pageentry_u8;
123     uint32_t *pageentry_u32;
124     uint16_t *pageentry_u16;
125
126     uint64_t last_bitmap;
127 #endif
128 } BDRVVPCState;
129
130 static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
131 {
132     if (buf_size >= 8 && !strncmp((char *)buf, "conectix", 8))
133         return 100;
134     return 0;
135 }
136
137 static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
138 {
139     BDRVVPCState *s = bs->opaque;
140     int ret, i;
141     struct vhd_footer* footer;
142     struct vhd_dyndisk_header* dyndisk_header;
143     uint8_t buf[HEADER_SIZE];
144
145     ret = bdrv_file_open(&s->hd, filename, flags);
146     if (ret < 0)
147         return ret;
148
149     if (bdrv_pread(s->hd, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
150         goto fail;
151
152     footer = (struct vhd_footer*) s->footer_buf;
153     if (strncmp(footer->creator, "conectix", 8))
154         goto fail;
155
156     // The visible size of a image in Virtual PC depends on the geometry
157     // rather than on the size stored in the footer (the size in the footer
158     // is too large usually)
159     bs->total_sectors = (int64_t)
160         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
161
162     if (bdrv_pread(s->hd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
163             != HEADER_SIZE)
164         goto fail;
165
166     dyndisk_header = (struct vhd_dyndisk_header*) buf;
167
168     if (strncmp(dyndisk_header->magic, "cxsparse", 8))
169         goto fail;
170
171
172     s->block_size = be32_to_cpu(dyndisk_header->block_size);
173     s->bitmap_size = ((s->block_size / (8 * 512)) + 511) & ~511;
174
175     s->max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries);
176     s->pagetable = qemu_malloc(s->max_table_entries * 4);
177     if (!s->pagetable)
178         goto fail;
179
180     s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
181     if (bdrv_pread(s->hd, s->bat_offset, s->pagetable,
182             s->max_table_entries * 4) != s->max_table_entries * 4)
183             goto fail;
184
185     s->free_data_block_offset =
186         (s->bat_offset + (s->max_table_entries * 4) + 511) & ~511;
187
188     for (i = 0; i < s->max_table_entries; i++) {
189         be32_to_cpus(&s->pagetable[i]);
190         if (s->pagetable[i] != 0xFFFFFFFF) {
191             int64_t next = (512 * (int64_t) s->pagetable[i]) +
192                 s->bitmap_size + s->block_size;
193
194             if (next> s->free_data_block_offset)
195                 s->free_data_block_offset = next;
196         }
197     }
198
199     s->last_bitmap_offset = (int64_t) -1;
200
201 #ifdef CACHE
202     s->pageentry_u8 = qemu_malloc(512);
203     if (!s->pageentry_u8)
204         goto fail;
205     s->pageentry_u32 = s->pageentry_u8;
206     s->pageentry_u16 = s->pageentry_u8;
207     s->last_pagetable = -1;
208 #endif
209
210     return 0;
211  fail:
212     bdrv_delete(s->hd);
213     return -1;
214 }
215
216 /*
217  * Returns the absolute byte offset of the given sector in the image file.
218  * If the sector is not allocated, -1 is returned instead.
219  *
220  * The parameter write must be 1 if the offset will be used for a write
221  * operation (the block bitmaps is updated then), 0 otherwise.
222  */
223 static inline int64_t get_sector_offset(BlockDriverState *bs,
224     int64_t sector_num, int write)
225 {
226     BDRVVPCState *s = bs->opaque;
227     uint64_t offset = sector_num * 512;
228     uint64_t bitmap_offset, block_offset;
229     uint32_t pagetable_index, pageentry_index;
230
231     pagetable_index = offset / s->block_size;
232     pageentry_index = (offset % s->block_size) / 512;
233
234     if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff)
235         return -1; // not allocated
236
237     bitmap_offset = 512 * s->pagetable[pagetable_index];
238     block_offset = bitmap_offset + s->bitmap_size + (512 * pageentry_index);
239
240     // We must ensure that we don't write to any sectors which are marked as
241     // unused in the bitmap. We get away with setting all bits in the block
242     // bitmap each time we write to a new block. This might cause Virtual PC to
243     // miss sparse read optimization, but it's not a problem in terms of
244     // correctness.
245     if (write && (s->last_bitmap_offset != bitmap_offset)) {
246         uint8_t bitmap[s->bitmap_size];
247
248         s->last_bitmap_offset = bitmap_offset;
249         memset(bitmap, 0xff, s->bitmap_size);
250         bdrv_pwrite(s->hd, bitmap_offset, bitmap, s->bitmap_size);
251     }
252
253 //    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
254 //      sector_num, pagetable_index, pageentry_index,
255 //      bitmap_offset, block_offset);
256
257 // disabled by reason
258 #if 0
259 #ifdef CACHE
260     if (bitmap_offset != s->last_bitmap)
261     {
262         lseek(s->fd, bitmap_offset, SEEK_SET);
263
264         s->last_bitmap = bitmap_offset;
265
266         // Scary! Bitmap is stored as big endian 32bit entries,
267         // while we used to look it up byte by byte
268         read(s->fd, s->pageentry_u8, 512);
269         for (i = 0; i < 128; i++)
270             be32_to_cpus(&s->pageentry_u32[i]);
271     }
272
273     if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
274         return -1;
275 #else
276     lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
277
278     read(s->fd, &bitmap_entry, 1);
279
280     if ((bitmap_entry >> (pageentry_index % 8)) & 1)
281         return -1; // not allocated
282 #endif
283 #endif
284
285     return block_offset;
286 }
287
288 /*
289  * Writes the footer to the end of the image file. This is needed when the
290  * file grows as it overwrites the old footer
291  *
292  * Returns 0 on success and < 0 on error
293  */
294 static int rewrite_footer(BlockDriverState* bs)
295 {
296     int ret;
297     BDRVVPCState *s = bs->opaque;
298     int64_t offset = s->free_data_block_offset;
299
300     ret = bdrv_pwrite(s->hd, offset, s->footer_buf, HEADER_SIZE);
301     if (ret < 0)
302         return ret;
303
304     return 0;
305 }
306
307 /*
308  * Allocates a new block. This involves writing a new footer and updating
309  * the Block Allocation Table to use the space at the old end of the image
310  * file (overwriting the old footer)
311  *
312  * Returns the sectors' offset in the image file on success and < 0 on error
313  */
314 static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
315 {
316     BDRVVPCState *s = bs->opaque;
317     int64_t bat_offset;
318     uint32_t index, bat_value;
319     int ret;
320     uint8_t bitmap[s->bitmap_size];
321
322     // Check if sector_num is valid
323     if ((sector_num < 0) || (sector_num > bs->total_sectors))
324         return -1;
325
326     // Write entry into in-memory BAT
327     index = (sector_num * 512) / s->block_size;
328     if (s->pagetable[index] != 0xFFFFFFFF)
329         return -1;
330
331     s->pagetable[index] = s->free_data_block_offset / 512;
332
333     // Initialize the block's bitmap
334     memset(bitmap, 0xff, s->bitmap_size);
335     bdrv_pwrite(s->hd, s->free_data_block_offset, bitmap, s->bitmap_size);
336
337     // Write new footer (the old one will be overwritten)
338     s->free_data_block_offset += s->block_size + s->bitmap_size;
339     ret = rewrite_footer(bs);
340     if (ret < 0)
341         goto fail;
342
343     // Write BAT entry to disk
344     bat_offset = s->bat_offset + (4 * index);
345     bat_value = be32_to_cpu(s->pagetable[index]);
346     ret = bdrv_pwrite(s->hd, bat_offset, &bat_value, 4);
347     if (ret < 0)
348         goto fail;
349
350     return get_sector_offset(bs, sector_num, 0);
351
352 fail:
353     s->free_data_block_offset -= (s->block_size + s->bitmap_size);
354     return -1;
355 }
356
357 static int vpc_read(BlockDriverState *bs, int64_t sector_num,
358                     uint8_t *buf, int nb_sectors)
359 {
360     BDRVVPCState *s = bs->opaque;
361     int ret;
362     int64_t offset;
363
364     while (nb_sectors > 0) {
365         offset = get_sector_offset(bs, sector_num, 0);
366
367         if (offset == -1) {
368             memset(buf, 0, 512);
369         } else {
370             ret = bdrv_pread(s->hd, offset, buf, 512);
371             if (ret != 512)
372                 return -1;
373         }
374
375         nb_sectors--;
376         sector_num++;
377         buf += 512;
378     }
379     return 0;
380 }
381
382 static int vpc_write(BlockDriverState *bs, int64_t sector_num,
383     const uint8_t *buf, int nb_sectors)
384 {
385     BDRVVPCState *s = bs->opaque;
386     int64_t offset;
387     int ret;
388
389     while (nb_sectors > 0) {
390         offset = get_sector_offset(bs, sector_num, 1);
391
392         if (offset == -1) {
393             offset = alloc_block(bs, sector_num);
394             if (offset < 0)
395                 return -1;
396         }
397
398         ret = bdrv_pwrite(s->hd, offset, buf, 512);
399         if (ret != 512)
400             return -1;
401
402         nb_sectors--;
403         sector_num++;
404         buf += 512;
405     }
406
407     return 0;
408 }
409
410 static void vpc_close(BlockDriverState *bs)
411 {
412     BDRVVPCState *s = bs->opaque;
413     qemu_free(s->pagetable);
414 #ifdef CACHE
415     qemu_free(s->pageentry_u8);
416 #endif
417     bdrv_delete(s->hd);
418 }
419
420 BlockDriver bdrv_vpc = {
421     "vpc",
422     sizeof(BDRVVPCState),
423     vpc_probe,
424     vpc_open,
425     vpc_read,
426     vpc_write,
427     vpc_close,
428 };