Revision 6a0f9e82

b/Changelog
22 22
  - Samba 3 support
23 23
  - initial Cocoa support (Pierre d'Herbemont)
24 24
  - generic FPU emulation code
25
  - Virtual PC read-only disk image support (Alex Beregszaszi)
25 26

  
26 27
version 0.6.1:
27 28

  
b/Makefile
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 block-bochs.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 block-vpc.c
29 29
	$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
30 30

  
31 31
dyngen$(EXESUF): dyngen.c
b/Makefile.target
313 313
endif
314 314

  
315 315
# must use static linking to avoid leaving stuff in virtual address space
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 block-bochs.o
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 block-bochs.o block-vpc.o
318 318

  
319 319
SOUND_HW = sb16.o
320 320
AUDIODRV = audio.o noaudio.o wavaudio.o
b/block-vpc.c
1
/*
2
 * Block driver for Conectix/Microsoft Virtual PC images
3
 * 
4
 * Copyright (c) 2005 Alex Beregszaszi
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25
#include "block_int.h"
26

  
27
/**************************************************************/
28

  
29
#define HEADER_SIZE 512
30

  
31
//#define CACHE
32

  
33
// always big-endian
34
struct vpc_subheader {
35
    char magic[8]; // "conectix" / "cxsparse"
36
    union {
37
	struct {
38
	    uint32_t unk1[2];
39
	    uint32_t unk2; // always zero?
40
	    uint32_t subheader_offset;
41
	    uint32_t unk3; // some size?
42
	    char creator[4]; // "vpc "
43
	    uint16_t major;
44
	    uint16_t minor;
45
	    char guest[4]; // "Wi2k"
46
	    uint32_t unk4[7];
47
	    uint8_t vnet_id[16]; // virtual network id, purpose unknown
48
	    // next 16 longs are used, but dunno the purpose
49
	    // next 6 longs unknown, following 7 long maybe a serial
50
	    char padding[HEADER_SIZE - 84];
51
	} main;
52
	struct {
53
	    uint32_t unk1[2]; // all bits set
54
	    uint32_t unk2; // always zero?
55
	    uint32_t pagetable_offset;
56
	    uint32_t unk3;
57
	    uint32_t pagetable_entries; // 32bit/entry
58
	    uint32_t pageentry_size; // 512*8*512
59
	    uint32_t nb_sectors;
60
	    char padding[HEADER_SIZE - 40];
61
	} sparse;
62
	char padding[HEADER_SIZE - 8];
63
    } type;
64
};
65

  
66
typedef struct BDRVVPCState {
67
    int fd;
68
    
69
    int pagetable_entries;
70
    uint32_t *pagetable;
71

  
72
    uint32_t pageentry_size;
73
#ifdef CACHE
74
    uint8_t *pageentry_u8;
75
    uint32_t *pageentry_u32;
76
    uint16_t *pageentry_u16;
77
    
78
    uint64_t last_bitmap;
79
#endif
80
} BDRVVPCState;
81

  
82
static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
83
{
84
    if (!strncmp(buf, "conectix", 8))
85
	return 100;
86

  
87
    return 0;
88
}
89

  
90
static int vpc_open(BlockDriverState *bs, const char *filename)
91
{
92
    BDRVVPCState *s = bs->opaque;
93
    int fd, i;
94
    struct vpc_subheader header;
95

  
96
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
97
    if (fd < 0) {
98
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
99
        if (fd < 0)
100
            return -1;
101
    }
102
    
103
    bs->read_only = 1; // no write support yet
104
    
105
    s->fd = fd;
106

  
107
    if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
108
        goto fail;
109

  
110
    if (strncmp(header.magic, "conectix", 8))
111
        goto fail;
112
    lseek(s->fd, be32_to_cpu(header.type.main.subheader_offset), SEEK_SET);
113

  
114
    if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
115
        goto fail;
116

  
117
    if (strncmp(header.magic, "cxsparse", 8))
118
	goto fail;
119

  
120
    bs->total_sectors = ((uint64_t)be32_to_cpu(header.type.sparse.pagetable_entries) *
121
			be32_to_cpu(header.type.sparse.pageentry_size)) / 512;
122

  
123
    lseek(s->fd, be32_to_cpu(header.type.sparse.pagetable_offset), SEEK_SET);
124

  
125
    s->pagetable_entries = be32_to_cpu(header.type.sparse.pagetable_entries);
126
    s->pagetable = qemu_malloc(s->pagetable_entries * 4);
127
    if (!s->pagetable)
128
	goto fail;
129
    if (read(s->fd, s->pagetable, s->pagetable_entries * 4) !=
130
	s->pagetable_entries * 4)
131
	goto fail;
132
    for (i = 0; i < s->pagetable_entries; i++)
133
	be32_to_cpus(&s->pagetable[i]);
134

  
135
    s->pageentry_size = be32_to_cpu(header.type.sparse.pageentry_size);
136
#ifdef CACHE
137
    s->pageentry_u8 = qemu_malloc(512);
138
    if (!s->pageentry_u8)
139
	goto fail;
140
    s->pageentry_u32 = s->pageentry_u8;
141
    s->pageentry_u16 = s->pageentry_u8;
142
    s->last_pagetable = -1;
143
#endif
144

  
145
    return 0;
146
 fail:
147
    close(fd);
148
    return -1;
149
}
150

  
151
static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
152
{
153
    BDRVVPCState *s = bs->opaque;
154
    uint64_t offset = sector_num * 512;
155
    uint64_t bitmap_offset, block_offset;
156
    uint32_t pagetable_index, pageentry_index;
157

  
158
    pagetable_index = offset / s->pageentry_size;
159
    pageentry_index = (offset % s->pageentry_size) / 512;
160
    
161
    if (pagetable_index > s->pagetable_entries || s->pagetable[pagetable_index] == 0xffffffff)
162
	return -1; // not allocated
163

  
164
    bitmap_offset = 512 * s->pagetable[pagetable_index];
165
    block_offset = bitmap_offset + 512 + (512 * pageentry_index);
166
    
167
//    printf("sector: %llx, index: %x, offset: %x, bioff: %llx, bloff: %llx\n",
168
//	sector_num, pagetable_index, pageentry_index,
169
//	bitmap_offset, block_offset);
170

  
171
// disabled by reason
172
#if 0
173
#ifdef CACHE
174
    if (bitmap_offset != s->last_bitmap)
175
    {
176
	lseek(s->fd, bitmap_offset, SEEK_SET);
177

  
178
	s->last_bitmap = bitmap_offset;
179
	
180
	// Scary! Bitmap is stored as big endian 32bit entries,
181
	// while we used to look it up byte by byte
182
	read(s->fd, s->pageentry_u8, 512);
183
	for (i = 0; i < 128; i++)
184
	    be32_to_cpus(&s->pageentry_u32[i]);
185
    }
186

  
187
    if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
188
	return -1;
189
#else
190
    lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
191
	
192
    read(s->fd, &bitmap_entry, 1);
193

  
194
    if ((bitmap_entry >> (pageentry_index % 8)) & 1)
195
	return -1; // not allocated
196
#endif
197
#endif
198
    lseek(s->fd, block_offset, SEEK_SET);
199

  
200
    return 0;
201
}
202

  
203
static int vpc_read(BlockDriverState *bs, int64_t sector_num, 
204
                    uint8_t *buf, int nb_sectors)
205
{
206
    BDRVVPCState *s = bs->opaque;
207
    int ret;
208

  
209
    while (nb_sectors > 0) {
210
	if (!seek_to_sector(bs, sector_num))
211
	{
212
	    ret = read(s->fd, buf, 512);
213
	    if (ret != 512)
214
		return -1;
215
	}
216
	else
217
            memset(buf, 0, 512);
218
        nb_sectors--;
219
        sector_num++;
220
        buf += 512;
221
    }
222
    return 0;
223
}
224

  
225
static void vpc_close(BlockDriverState *bs)
226
{
227
    BDRVVPCState *s = bs->opaque;
228
    qemu_free(s->pagetable);
229
#ifdef CACHE
230
    qemu_free(s->pageentry_u8);
231
#endif
232
    close(s->fd);
233
}
234

  
235
BlockDriver bdrv_vpc = {
236
    "vpc",
237
    sizeof(BDRVVPCState),
238
    vpc_probe,
239
    vpc_open,
240
    vpc_read,
241
    NULL,
242
    vpc_close,
243
};
b/block.c
652 652
    bdrv_register(&bdrv_cloop);
653 653
    bdrv_register(&bdrv_dmg);
654 654
    bdrv_register(&bdrv_bochs);
655
    bdrv_register(&bdrv_vpc);
655 656
}
b/vl.h
383 383
extern BlockDriver bdrv_cloop;
384 384
extern BlockDriver bdrv_dmg;
385 385
extern BlockDriver bdrv_bochs;
386
extern BlockDriver bdrv_vpc;
386 387

  
387 388
void bdrv_init(void);
388 389
BlockDriver *bdrv_find_format(const char *format_name);

Also available in: Unified diff