Commit a8753c3466dcf5c08f51313a402eb09be5af7e30

Authored by bellard
1 parent c99280bc

Bochs disk image support (Alex Beregszaszi)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1409 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
1   -version 0.6.2:
  1 +version 0.7.0:
2 2  
3 3 - better BIOS translation and HDD geometry auto-detection
4 4 - user mode networking bug fix
... ... @@ -9,15 +9,19 @@ version 0.6.2:
9 9 - keymaps support (initial patch by Johannes Schindelin)
10 10 - big endian ARM support (Lennert Buytenhek)
11 11 - added generic 64 bit target support
12   - - initial x86_64 target support
  12 + - x86_64 target support
13 13 - initial APIC support
14 14 - MMX/SSE/SSE2/PNI support
15 15 - PC parallel port support (Mark Jonckheere)
16 16 - initial SPARC64 support (Blue Swirl)
  17 + - SPARC target boots Linux (Blue Swirl)
17 18 - armv5te user mode support (Paul Brook)
18 19 - ARM VFP support (Paul Brook)
  20 + - ARM "Angel" semihosting syscalls (Paul Brook)
  21 + - user mode gdb stub support (Paul Brook)
19 22 - Samba 3 support
20 23 - initial Cocoa support (Pierre d'Herbemont)
  24 + - generic FPU emulation code
21 25  
22 26 version 0.6.1:
23 27  
... ...
Makefile
... ... @@ -25,7 +25,7 @@ else
25 25 endif
26 26 endif
27 27  
28   -qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c
  28 +qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c
29 29 $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
30 30  
31 31 dyngen$(EXESUF): dyngen.c
... ...
Makefile.target
... ... @@ -314,7 +314,7 @@ endif
314 314  
315 315 # must use static linking to avoid leaving stuff in virtual address space
316 316 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
317   -VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o
  317 +VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o
318 318  
319 319 SOUND_HW = sb16.o
320 320 AUDIODRV = audio.o noaudio.o wavaudio.o
... ...
block-bochs.c 0 → 100644
  1 +/*
  2 + * Block driver for the various disk image formats used by Bochs
  3 + * Currently only for "growing" type in read-only mode
  4 + *
  5 + * Copyright (c) 2005 Alex Beregszaszi
  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 "vl.h"
  26 +#include "block_int.h"
  27 +
  28 +/**************************************************************/
  29 +
  30 +#define HEADER_MAGIC "Bochs Virtual HD Image"
  31 +#define HEADER_VERSION 0x00010000
  32 +#define HEADER_SIZE 512
  33 +
  34 +#define REDOLOG_TYPE "Redolog"
  35 +#define GROWING_TYPE "Growing"
  36 +
  37 +// not allocated: 0xffffffff
  38 +
  39 +// always little-endian
  40 +struct bochs_header {
  41 + char magic[32]; // "Bochs Virtual HD Image"
  42 + char type[16]; // "Redolog"
  43 + char subtype[16]; // "Undoable" / "Volatile" / "Growing"
  44 + uint32_t version;
  45 + uint32_t header; // size of header
  46 +
  47 + union {
  48 + struct {
  49 + uint32_t catalog; // num of entries
  50 + uint32_t bitmap; // bitmap size
  51 + uint32_t extent; // extent size
  52 + uint64_t disk; // disk size
  53 + char padding[HEADER_SIZE - 64 - 8 - 20];
  54 + } redolog;
  55 + char padding[HEADER_SIZE - 64 - 8];
  56 + } extra;
  57 +};
  58 +
  59 +typedef struct BDRVBochsState {
  60 + int fd;
  61 +
  62 + uint32_t *catalog_bitmap;
  63 + int catalog_size;
  64 +
  65 + int data_offset;
  66 +
  67 + int bitmap_blocks;
  68 + int extent_blocks;
  69 + int extent_size;
  70 +} BDRVBochsState;
  71 +
  72 +static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
  73 +{
  74 + const struct bochs_header *bochs = (const void *)buf;
  75 +
  76 + if (buf_size < HEADER_SIZE)
  77 + return 0;
  78 +
  79 + if (!strcmp(bochs->magic, HEADER_MAGIC) &&
  80 + !strcmp(bochs->type, REDOLOG_TYPE) &&
  81 + !strcmp(bochs->subtype, GROWING_TYPE) &&
  82 + (le32_to_cpu(bochs->version) == HEADER_VERSION))
  83 + return 100;
  84 +
  85 + return 0;
  86 +}
  87 +
  88 +static int bochs_open(BlockDriverState *bs, const char *filename)
  89 +{
  90 + BDRVBochsState *s = bs->opaque;
  91 + int fd, i;
  92 + struct bochs_header bochs;
  93 +
  94 + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  95 + if (fd < 0) {
  96 + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  97 + if (fd < 0)
  98 + return -1;
  99 + }
  100 +
  101 + bs->read_only = 1; // no write support yet
  102 +
  103 + s->fd = fd;
  104 +
  105 + if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
  106 + goto fail;
  107 + }
  108 +
  109 + if (strcmp(bochs.magic, HEADER_MAGIC) ||
  110 + strcmp(bochs.type, REDOLOG_TYPE) ||
  111 + strcmp(bochs.subtype, GROWING_TYPE) ||
  112 + (le32_to_cpu(bochs.version) != HEADER_VERSION)) {
  113 + goto fail;
  114 + }
  115 +
  116 + bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
  117 +
  118 + lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
  119 +
  120 + s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
  121 + s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
  122 + if (!s->catalog_bitmap)
  123 + goto fail;
  124 + if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
  125 + s->catalog_size * 4)
  126 + goto fail;
  127 + for (i = 0; i < s->catalog_size; i++)
  128 + le32_to_cpus(&s->catalog_bitmap[i]);
  129 +
  130 + s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
  131 +
  132 + s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
  133 + s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
  134 +
  135 + s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
  136 +
  137 + return 0;
  138 + fail:
  139 + close(fd);
  140 + return -1;
  141 +}
  142 +
  143 +static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
  144 +{
  145 + BDRVBochsState *s = bs->opaque;
  146 + int64_t offset = sector_num * 512;
  147 + int64_t extent_index, extent_offset, bitmap_offset, block_offset;
  148 + char bitmap_entry;
  149 +
  150 + // seek to sector
  151 + extent_index = offset / s->extent_size;
  152 + extent_offset = (offset % s->extent_size) / 512;
  153 +
  154 + if (s->catalog_bitmap[extent_index] == 0xffffffff)
  155 + {
  156 +// fprintf(stderr, "page not allocated [%x - %x:%x]\n",
  157 +// sector_num, extent_index, extent_offset);
  158 + return -1; // not allocated
  159 + }
  160 +
  161 + bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
  162 + (s->extent_blocks + s->bitmap_blocks));
  163 + block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
  164 +
  165 +// fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
  166 +// sector_num, extent_index, extent_offset,
  167 +// le32_to_cpu(s->catalog_bitmap[extent_index]),
  168 +// bitmap_offset, block_offset);
  169 +
  170 + // read in bitmap for current extent
  171 + lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
  172 +
  173 + read(s->fd, &bitmap_entry, 1);
  174 +
  175 + if (!((bitmap_entry >> (extent_offset % 8)) & 1))
  176 + {
  177 +// fprintf(stderr, "sector (%x) in bitmap not allocated\n",
  178 +// sector_num);
  179 + return -1; // not allocated
  180 + }
  181 +
  182 + lseek(s->fd, block_offset, SEEK_SET);
  183 +
  184 + return 0;
  185 +}
  186 +
  187 +static int bochs_read(BlockDriverState *bs, int64_t sector_num,
  188 + uint8_t *buf, int nb_sectors)
  189 +{
  190 + BDRVBochsState *s = bs->opaque;
  191 + int ret;
  192 +
  193 + while (nb_sectors > 0) {
  194 + if (!seek_to_sector(bs, sector_num))
  195 + {
  196 + ret = read(s->fd, buf, 512);
  197 + if (ret != 512)
  198 + return -1;
  199 + }
  200 + else
  201 + memset(buf, 0, 512);
  202 + nb_sectors--;
  203 + sector_num++;
  204 + buf += 512;
  205 + }
  206 + return 0;
  207 +}
  208 +
  209 +static void bochs_close(BlockDriverState *bs)
  210 +{
  211 + BDRVBochsState *s = bs->opaque;
  212 + qemu_free(s->catalog_bitmap);
  213 + close(s->fd);
  214 +}
  215 +
  216 +BlockDriver bdrv_bochs = {
  217 + "bochs",
  218 + sizeof(BDRVBochsState),
  219 + bochs_probe,
  220 + bochs_open,
  221 + bochs_read,
  222 + NULL,
  223 + bochs_close,
  224 +};
... ...
... ... @@ -608,4 +608,5 @@ void bdrv_init(void)
608 608 bdrv_register(&bdrv_vmdk);
609 609 bdrv_register(&bdrv_cloop);
610 610 bdrv_register(&bdrv_dmg);
  611 + bdrv_register(&bdrv_bochs);
611 612 }
... ...
... ... @@ -382,6 +382,7 @@ extern BlockDriver bdrv_qcow;
382 382 extern BlockDriver bdrv_vmdk;
383 383 extern BlockDriver bdrv_cloop;
384 384 extern BlockDriver bdrv_dmg;
  385 +extern BlockDriver bdrv_bochs;
385 386  
386 387 void bdrv_init(void);
387 388 BlockDriver *bdrv_find_format(const char *format_name);
... ...