--- vl.h Sun May 7 23:24:35 2006 +++ vl.h Sun May 7 23:24:47 2006 @@ -477,6 +477,7 @@ extern BlockDriver bdrv_bochs; extern BlockDriver bdrv_vpc; extern BlockDriver bdrv_vvfat; +extern BlockDriver bdrv_part; void bdrv_init(void); BlockDriver *bdrv_find_format(const char *format_name); --- Makefile.target Sun May 7 23:25:52 2006 +++ Makefile.target Sun May 7 23:26:04 2006 @@ -273,7 +273,7 @@ # must use static linking to avoid leaving stuff in virtual address space VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o -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 +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-part.o ifdef CONFIG_WIN32 VL_OBJS+=tap-win32.o endif --- block.c Sun May 7 23:22:40 2006 +++ block.c Sun May 7 23:22:25 2006 @@ -794,4 +794,5 @@ bdrv_register(&bdrv_bochs); bdrv_register(&bdrv_vpc); bdrv_register(&bdrv_vvfat); + bdrv_register(&bdrv_part); } --- Makefile Sun May 7 23:38:56 2006 +++ Makefile Sun May 7 23:16:20 2006 @@ -22,7 +22,7 @@ $(MAKE) -C $$d $@ || exit 1 ; \ done -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 block-vvfat.c +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 block-vvfat.c block-part.c $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) dyngen$(EXESUF): dyngen.c --- /dev/null Wed Apr 19 17:19:14 2006 +++ block-part.c Mon May 8 10:33:52 2006 @@ -0,0 +1,223 @@ +/* + * Block driver to use partition images instead of whole hard disk images + * + * Copyright (c) 2006 Jim Brown + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" + +#ifdef __sun__ +#include +#endif + +typedef struct BDRVPartState { + char mbr_data[63*512]; + BlockDriverState * slave_bs; +} BDRVPartState; + +static int part_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + if (strstart(filename, "part:", NULL)) + return 100; + return 0; +} + +static int part_open(BlockDriverState *bs, const char *nfilename) +{ + BDRVPartState *s = bs->opaque; + BlockDriverState * slave_bs; + int boot_fd; + int64_t size; + int head, cylinder, sector; + const char * filename = &(nfilename[5]); + + slave_bs = qemu_mallocz(sizeof(BlockDriverState)); + if (bdrv_open2(slave_bs, filename, 0, NULL) != 0) + { + qemu_free(slave_bs); + return -1; + } + + s->slave_bs = slave_bs; + bs->read_only = slave_bs->read_only; + bs->total_sectors = slave_bs->total_sectors + 63; + + /* set up c/h/s */ + size = bs->total_sectors*512; + cylinder = size/(63*16); + /* FIXME */ + cylinder = cylinder + 1; /* add a cylinder just in case partition extends beyond the edge of the last cylinder/head/track */ + head = 16; + sector = 63; + /* some bit twiddling here */ + sector = (((cylinder >> 8) & 3) << 6) + sector; + + /* set up fake MBR */ + memset(s->mbr_data, 0, 63*512); + boot_fd = open("bootmbr.bin", O_RDONLY); + if (boot_fd == -1) + { + printf("Warning: failed to open bootsector.bin - MBR will not be bootable\n"); + } + else + { + if (read(boot_fd, s->mbr_data, 512) == -1) + { + printf("Warning: failed to read bootsector.bin - MBR will not be bootbale\n"); + } + close(boot_fd); + } + /* first partition is bootable */ + s->mbr_data[446] = 0x80; + /* start head */ + s->mbr_data[447] = 0x01; + /* start sector - only first 6 bits */ + s->mbr_data[448] = 0x01; + /* start cylinder - this byte plus 2 bits from mbr_data[447] */ + s->mbr_data[449] = 0x00; + /* system ID */ + s->mbr_data[450] = 0x0C; /* say we're win98 fat32 */ + /* ending head */ + s->mbr_data[451] = head; + /* ending sector */ + s->mbr_data[452] = sector; + /* ending cylinder */ + s->mbr_data[453] = cylinder; + /* absolute start sector - 4 bytes/DWORD */ + s->mbr_data[454] = 0x3F; // 3F = 63 + /* absolute total number of sectors - 4 bytes/DWORD */ + *((uint32_t*)(s->mbr_data+458)) = cpu_to_le32(bs->total_sectors - 63); + /* leave the other partitions blank - we only support the first one */ + + /* set the MBR sector signature */ + s->mbr_data[510] = 0x55; + s->mbr_data[511] = 0xAA; + + return 0; +} + +static int part_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVPartState *s = bs->opaque; + int ret,split; + + if (sector_num >= 63) + { + + ret = bdrv_read(s->slave_bs, sector_num-63, buf, nb_sectors); + if (ret != 0) + return -1; + return 0; + + } + else + { + + if ((nb_sectors + sector_num) > 63) + { + /* ah hell - we have to do both the fake part and the real part */ + + split = nb_sectors + sector_num - 63; + ret = part_read(bs, 63, &buf[(nb_sectors-split)*512], split * 512); + //if (ret != split * 512) + if (ret != 0) + return -1; + + /* this will always return 0 */ + ret = part_read(bs, sector_num, buf, (nb_sectors - split) * 512); + return 0; + } + else + { + memcpy(buf, &(s->mbr_data[sector_num*512]), nb_sectors*512); + return 0; + } + + } +} + +static int part_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVPartState *s = bs->opaque; + int ret, split; + + if (sector_num >= 63) + { + + ret = bdrv_write(s->slave_bs, sector_num-63, buf, nb_sectors); + if (ret != 0) + return -1; + return 0; + + } + else + { + + if ((nb_sectors + sector_num) > 63) + { + /* ah hell - we have to do both the fake part and the real part */ + + split = nb_sectors + sector_num - 63; + ret = part_write(bs, 63, &buf[(nb_sectors-split)*512], split * 512); + if (ret != split * 512) + return -1; + + /* this will always return 0 */ + ret = part_write(bs, sector_num, buf, (nb_sectors - split) * 512); + return 0; + } + else + { + memcpy(&(s->mbr_data[sector_num*512]), buf, nb_sectors*512); + return 0; + } + + } +} + +static void part_close(BlockDriverState *bs) +{ + BDRVPartState *s = bs->opaque; + bdrv_close(s->slave_bs); + qemu_free(s->slave_bs); + s->slave_bs = NULL; +} + +static int part_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + /* what would be the point... just make a raw or qcow */ + return -ENOTSUP; +} + +BlockDriver bdrv_part = { + "part", + sizeof(BDRVPartState), + part_probe, + part_open, + part_read, + part_write, + part_close, + part_create, +}; +