On Mon, May 08, 2006 at 08:26:20AM -0400, Jim C. Brown wrote:
> > - Instead of copying the raw block driver, use the block driver recursively.
> 
> I'll work on this tonight. I've been thinking about doing this, since it would
> allow one to use any qemu-supported disk image format as a partition image.
> 
> > 
> > Fabrice.
> > 
> 

New patch here. Apply directly to qemu cvs (i.e. don't apply any of the older
patches).

I've only tested raw partition images and the vvfat driver (in floppy disk mode
of course) with this, but it should work with any format.

("-hda part:fat:floppy:/dir" is what I used)

Now to hack up a fake bootsector so we can boot vvfat partitions. ;)

-- 
Infinite complexity begets infinite beauty.
Infinite precision begets infinite perfection.
--- 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 <sys/dkio.h>
+#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,
+};
+
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to