--- 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_raw; 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-raw.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_raw); } --- 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-raw.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-raw.c Sun May 7 23:21:52 2006 @@ -0,0 +1,249 @@ +/* + * 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 BDRVPartRawState { + char mbr_data[63*512]; + int fd; +} BDRVPartRawState; + +static int part_raw_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + if (strstart(filename, "part:", NULL)) + return 100; + return 0; +} + +static int part_raw_open(BlockDriverState *bs, const char *filename) +{ + BDRVPartRawState *s = bs->opaque; + int fd; + int64_t size; +#ifdef _BSD + struct stat sb; +#endif +#ifdef __sun__ + struct dk_minfo minfo; + int rv; +#endif + int head, cylinder, sector; + + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + if (fd < 0) { + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + bs->read_only = 1; + } +#ifdef _BSD + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { +#ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) +#endif +#ifdef CONFIG_COCOA + size = LONG_LONG_MAX; +#else + size = lseek(fd, 0LL, SEEK_END); +#endif + } else +#endif +#ifdef __sun__ + /* + * use the DKIOCGMEDIAINFO ioctl to read the size. + */ + rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); + if ( rv != -1 ) { + size = minfo.dki_lbsize * minfo.dki_capacity; + } else /* there are reports that lseek on some devices + fails, but irc discussion said that contingency + on contingency was overkill */ +#endif + { + size = lseek(fd, 0, SEEK_END); + } + bs->total_sectors = (size / 512) + 63; + s->fd = fd; + + /* set up c/h/s */ + size = size+(63*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); + /* 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_raw_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVPartRawState *s = bs->opaque; + int ret,split; + + if (sector_num >= 63) + { + + lseek(s->fd, (sector_num - 63) * 512, SEEK_SET); + ret = read(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + 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_raw_read(bs, 63, &buf[(nb_sectors-split)*512], split * 512); + if (ret != split * 512) + return -1; + + /* this will always return 0 */ + ret = part_raw_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_raw_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVPartRawState *s = bs->opaque; + int ret, split; + + if (sector_num >= 63) + { + + lseek(s->fd, (sector_num - 63) * 512, SEEK_SET); + ret = write(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + 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_raw_write(bs, 63, &buf[(nb_sectors-split)*512], split * 512); + if (ret != split * 512) + return -1; + + /* this will always return 0 */ + ret = part_raw_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_raw_close(BlockDriverState *bs) +{ + BDRVPartRawState *s = bs->opaque; + close(s->fd); +} + +static int part_raw_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + int fd; + + if (flags || backing_file) + return -ENOTSUP; + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + 0644); + if (fd < 0) + return -EIO; + ftruncate(fd, total_size * 512); + close(fd); + return 0; +} + +BlockDriver bdrv_part_raw = { + "part_raw", + sizeof(BDRVPartRawState), + part_raw_probe, + part_raw_open, + part_raw_read, + part_raw_write, + part_raw_close, + part_raw_create, +}; +