Commit 6ada7453aa628cb6ed58e1cfd3119c90382ad017

Authored by ths
1 parent 96cf2df8

Parallels disk image support, by Alex Beregszaszi.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3102 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -10,6 +10,7 @@
10 10 - Improved SH4 support (Magnus Damm)
11 11 - MIPS64 support (Aurelien Jarno, Thiemo Seufer)
12 12 - Preliminary Alpha guest support (J. Mayer)
  13 + - Read-only support for Parallels disk images (Alex Beregszaszi)
13 14  
14 15 version 0.9.0:
15 16  
... ...
Makefile
... ... @@ -32,7 +32,7 @@ subdir-%: dyngen$(EXESUF)
32 32  
33 33 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
34 34  
35   -qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
  35 +qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c block-parallels.c
36 36 $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
37 37  
38 38 dyngen$(EXESUF): dyngen.c
... ...
Makefile.target
... ... @@ -367,7 +367,7 @@ VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
367 367 VL_OBJS+=cutils.o
368 368 VL_OBJS+=host-utils.o
369 369 VL_OBJS+=block.o block-raw.o
370   -VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
  370 +VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o block-parallels.o
371 371 VL_OBJS+=irq.o
372 372 ifdef CONFIG_WIN32
373 373 VL_OBJS+=tap-win32.o
... ...
block-parallels.c 0 → 100644
  1 +/*
  2 + * Block driver for Parallels disk image format
  3 + *
  4 + * Copyright (c) 2007 Alex Beregszaszi
  5 + *
  6 + * This code is based on comparing different disk images created by Parallels.
  7 + *
  8 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  9 + * of this software and associated documentation files (the "Software"), to deal
  10 + * in the Software without restriction, including without limitation the rights
  11 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 + * copies of the Software, and to permit persons to whom the Software is
  13 + * furnished to do so, subject to the following conditions:
  14 + *
  15 + * The above copyright notice and this permission notice shall be included in
  16 + * all copies or substantial portions of the Software.
  17 + *
  18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 + * THE SOFTWARE.
  25 + */
  26 +#include "vl.h"
  27 +#include "block_int.h"
  28 +
  29 +/**************************************************************/
  30 +
  31 +#define HEADER_MAGIC "WithoutFreeSpace"
  32 +#define HEADER_VERSION 2
  33 +#define HEADER_SIZE 64
  34 +
  35 +// always little-endian
  36 +struct parallels_header {
  37 + char magic[16]; // "WithoutFreeSpace"
  38 + uint32_t version;
  39 + uint32_t heads;
  40 + uint32_t cylinders;
  41 + uint32_t tracks;
  42 + uint32_t catalog_entries;
  43 + uint32_t nb_sectors;
  44 + char padding[24];
  45 +} __attribute__((packed));
  46 +
  47 +typedef struct BDRVParallelsState {
  48 + int fd;
  49 +
  50 + uint32_t *catalog_bitmap;
  51 + int catalog_size;
  52 +
  53 + int tracks;
  54 +} BDRVParallelsState;
  55 +
  56 +static int parallels_probe(const uint8_t *buf, int buf_size, const char *filename)
  57 +{
  58 + const struct parallels_header *ph = (const void *)buf;
  59 +
  60 + if (buf_size < HEADER_SIZE)
  61 + return 0;
  62 +
  63 + if (!memcmp(ph->magic, HEADER_MAGIC, 16) &&
  64 + (le32_to_cpu(ph->version) == HEADER_VERSION))
  65 + return 100;
  66 +
  67 + return 0;
  68 +}
  69 +
  70 +static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
  71 +{
  72 + BDRVParallelsState *s = bs->opaque;
  73 + int fd, i;
  74 + struct parallels_header ph;
  75 +
  76 + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  77 + if (fd < 0) {
  78 + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  79 + if (fd < 0)
  80 + return -1;
  81 + }
  82 +
  83 + bs->read_only = 1; // no write support yet
  84 +
  85 + s->fd = fd;
  86 +
  87 + if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
  88 + goto fail;
  89 +
  90 + if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
  91 + (le32_to_cpu(ph.version) != HEADER_VERSION)) {
  92 + goto fail;
  93 + }
  94 +
  95 + bs->total_sectors = le32_to_cpu(ph.nb_sectors);
  96 +
  97 + if (lseek(s->fd, 64, SEEK_SET) != 64)
  98 + goto fail;
  99 +
  100 + s->tracks = le32_to_cpu(ph.tracks);
  101 +
  102 + s->catalog_size = le32_to_cpu(ph.catalog_entries);
  103 + s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
  104 + if (!s->catalog_bitmap)
  105 + goto fail;
  106 + if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
  107 + s->catalog_size * 4)
  108 + goto fail;
  109 + for (i = 0; i < s->catalog_size; i++)
  110 + le32_to_cpus(&s->catalog_bitmap[i]);
  111 +
  112 + return 0;
  113 +fail:
  114 + if (s->catalog_bitmap)
  115 + qemu_free(s->catalog_bitmap);
  116 + close(fd);
  117 + return -1;
  118 +}
  119 +
  120 +static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
  121 +{
  122 + BDRVParallelsState *s = bs->opaque;
  123 + uint32_t index, offset, position;
  124 +
  125 + index = sector_num / s->tracks;
  126 + offset = sector_num % s->tracks;
  127 +
  128 + // not allocated
  129 + if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
  130 + return -1;
  131 +
  132 + position = (s->catalog_bitmap[index] + offset) * 512;
  133 +
  134 +// fprintf(stderr, "sector: %llx index=%x offset=%x pointer=%x position=%x\n",
  135 +// sector_num, index, offset, s->catalog_bitmap[index], position);
  136 +
  137 + if (lseek(s->fd, position, SEEK_SET) != position)
  138 + return -1;
  139 +
  140 + return 0;
  141 +}
  142 +
  143 +static int parallels_read(BlockDriverState *bs, int64_t sector_num,
  144 + uint8_t *buf, int nb_sectors)
  145 +{
  146 + BDRVParallelsState *s = bs->opaque;
  147 +
  148 + while (nb_sectors > 0) {
  149 + if (!seek_to_sector(bs, sector_num)) {
  150 + if (read(s->fd, buf, 512) != 512)
  151 + return -1;
  152 + } else
  153 + memset(buf, 0, 512);
  154 + nb_sectors--;
  155 + sector_num++;
  156 + buf += 512;
  157 + }
  158 + return 0;
  159 +}
  160 +
  161 +static void parallels_close(BlockDriverState *bs)
  162 +{
  163 + BDRVParallelsState *s = bs->opaque;
  164 + qemu_free(s->catalog_bitmap);
  165 + close(s->fd);
  166 +}
  167 +
  168 +BlockDriver bdrv_parallels = {
  169 + "parallels",
  170 + sizeof(BDRVParallelsState),
  171 + parallels_probe,
  172 + parallels_open,
  173 + parallels_read,
  174 + NULL,
  175 + parallels_close,
  176 +};
... ...
... ... @@ -1241,6 +1241,7 @@ void bdrv_init(void)
1241 1241 bdrv_register(&bdrv_vpc);
1242 1242 bdrv_register(&bdrv_vvfat);
1243 1243 bdrv_register(&bdrv_qcow2);
  1244 + bdrv_register(&bdrv_parallels);
1244 1245 }
1245 1246  
1246 1247 void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
... ...
... ... @@ -570,6 +570,7 @@ extern BlockDriver bdrv_bochs;
570 570 extern BlockDriver bdrv_vpc;
571 571 extern BlockDriver bdrv_vvfat;
572 572 extern BlockDriver bdrv_qcow2;
  573 +extern BlockDriver bdrv_parallels;
573 574  
574 575 typedef struct BlockDriverInfo {
575 576 /* in bytes, 0 if irrelevant */
... ...