qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] [RFC] aio update for composite and partition block


From: jma5
Subject: [Qemu-devel] [PATCH] [RFC] aio update for composite and partition block drivers and a fix for -kernel boot
Date: Wed, 7 Mar 2007 13:56:35 -0500 (EST)

block-composite now fully supports AIO.

block-partition's MBR geometry has been fixed, linux fdisk no longer complains 
about a mismatch between logical and physical geometry.

Pretty much the only thing remaining is to clean up the syntax.

I've also included a second patch that fixes -kernel boot so a supporting -hda 
is no longer required. (This has been moved to -fda instead, additionally the 
block-ram driver is used if the floppy disk is booted up empty and 
automatically unloaded after the kernel has started booting.)
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/Makefile qemu.notlast/Makefile
--- qemu/Makefile       Sat Feb 10 18:00:33 2007
+++ qemu.notlast/Makefile       Wed Mar  7 10:34:09 2007
@@ -37,7 +37,7 @@
 
 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
 
-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
+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-composite.c block-ram.c 
block-partition.c
        $(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) 
$(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
 
 dyngen$(EXESUF): dyngen.c
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/Makefile.target qemu.notlast/Makefile.target
--- qemu/Makefile.target        Wed Feb 28 16:36:41 2007
+++ qemu.notlast/Makefile.target        Wed Mar  7 10:34:33 2007
@@ -322,7 +322,7 @@
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
 VL_OBJS+=cutils.o
-VL_OBJS+=block.o block-raw.o
+VL_OBJS+=block.o block-raw.o block-composite.o block-ram.o block-partition.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-qcow2.o
 ifdef CONFIG_WIN32
 VL_OBJS+=tap-win32.o
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/block-composite.c qemu.notlast/block-composite.c
--- qemu/block-composite.c      Wed Dec 31 19:00:00 1969
+++ qemu.notlast/block-composite.c      Wed Mar  7 10:45:18 2007
@@ -0,0 +1,552 @@
+/*
+ * Block driver to use composite images
+ * 
+ * Copyright (c) 2007 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 "block_composite.h"
+
+static int composite_probe(const uint8_t *buf, int buf_size, const char 
*filename)
+{
+    if (strstart(filename, "composite:", NULL))
+        return 100;
+    return 0;
+}
+
+static int composite_open(BlockDriverState *bs, const char *nfilename, int 
flags)
+{
+    BDRVPartState *s = bs->opaque;
+    BlockDriverState * slave_bs;
+    int previous_start, file_count = 1, i;
+    const char * zfilename = &(nfilename[10]), * nptr = zfilename;
+    char * filename;
+
+    bs->read_only = 0;
+    s->slave_count = 0;
+    previous_start = 0;
+
+    while (nptr != NULL)
+    {
+       nptr = strchr(nptr, ',')+1;
+       if ((nptr-1) != NULL)
+       {
+               file_count++;
+       }
+       else
+       {
+               nptr = NULL;
+       }
+    }
+    s->slave_bs = qemu_mallocz(sizeof(SlaveDriverState)*file_count);
+    if (s->slave_bs == NULL) return -1;
+    nptr = zfilename;
+
+    while (nptr != NULL)
+    {
+       nptr = strchr(zfilename, ',')+1;
+       if ((nptr-1) != NULL)
+       {
+               filename = strndup(zfilename, (size_t)((nptr-1)-zfilename));
+               zfilename = nptr;
+       }
+       else
+       {
+               filename = strdup(zfilename);
+               nptr = NULL;
+       }
+
+       slave_bs = qemu_mallocz(sizeof(BlockDriverState));
+       if ((slave_bs == NULL) || (bdrv_open2(slave_bs, filename, 0, NULL) != 
0))
+       {
+               for (i = 0; i < s->slave_count; i++)
+               {
+                       bdrv_close(s->slave_bs[i].bs);
+                       qemu_free(s->slave_bs[i].bs);
+               }
+               qemu_free(s->slave_bs);
+               return -1;
+       }
+       free(filename);
+
+       s->slave_bs[s->slave_count].bs = slave_bs;
+       s->slave_bs[s->slave_count].start_sector = previous_start;
+       previous_start = previous_start + 
s->slave_bs[s->slave_count].bs->total_sectors;
+       s->slave_count++;
+       if (slave_bs->read_only)
+       {
+               bs->read_only = 1;
+       }
+    }
+
+    bs->total_sectors = previous_start;
+
+    return 0;
+}
+
+static int composite_read(BlockDriverState *bs, int64_t sector_num, 
+                    uint8_t *buf, int nb_sectors)
+{
+    BDRVPartState *s = bs->opaque;
+    int ret,sstart,send,i;
+
+    sstart = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if ((s->slave_bs[i].start_sector +
+                           s->slave_bs[i].bs->total_sectors > sector_num)
+                           && (s->slave_bs[i].start_sector <= sector_num))
+           {
+                   sstart = i;
+                   break;
+           }
+    }
+    if (sstart == -1) return -1;
+
+    send = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
+                           > sector_num+nb_sectors)
+                           && (s->slave_bs[i].start_sector
+                           <= sector_num+nb_sectors))
+           {
+                   send = i;
+                   break;
+           }
+    }
+    if (send == -1) return -1;
+
+    if (sstart > send) return -2; //wtf???
+
+    int a = 0, b = 0, bufpos = 0;
+    i = sstart;
+    while (i < send)
+    {
+           a = s->slave_bs[i].bs->total_sectors;
+           ret = bdrv_read(s->slave_bs[i].bs, sector_num+b - 
s->slave_bs[i].start_sector, &(buf[bufpos]), a);
+           if (ret != 0) return ret;
+           b = b+a;
+           bufpos = bufpos + (a * 512);
+           i++;
+    }
+    return bdrv_read(s->slave_bs[send].bs, sector_num+b - 
s->slave_bs[send].start_sector, &(buf[bufpos]), nb_sectors-b);
+}
+
+static int composite_write(BlockDriverState *bs, int64_t sector_num, 
+                     const uint8_t *buf, int nb_sectors)
+{
+    BDRVPartState *s = bs->opaque;
+    int ret,sstart,send,i;
+
+    sstart = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if ((s->slave_bs[i].start_sector +
+                           s->slave_bs[i].bs->total_sectors > sector_num)
+                           && (s->slave_bs[i].start_sector <= sector_num))
+           {
+                   sstart = i;
+                   break;
+           }
+    }
+    if (sstart == -1) return -1;
+
+    send = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
+                           > sector_num+nb_sectors)
+                           && (s->slave_bs[i].start_sector
+                           <= sector_num+nb_sectors))
+           {
+                   send = i;
+                   break;
+           }
+    }
+    if (send == -1) return -1;
+
+    if (sstart > send) return -2; //wtf???
+
+    int a = 0, b = 0, bufpos = 0;
+    i = sstart;
+    while (i < send)
+    {
+           a = s->slave_bs[i].bs->total_sectors;
+           ret = bdrv_write(s->slave_bs[i].bs, sector_num+b - 
s->slave_bs[i].start_sector, &(buf[bufpos]), a);
+           if (ret != 0) return ret;
+           b = b+a;
+           bufpos = bufpos + (a * 512);
+           i++;
+    }
+    i= bdrv_write(s->slave_bs[send].bs, sector_num+b - 
s->slave_bs[send].start_sector, &(buf[bufpos]), nb_sectors-b);
+    return i;
+}
+
+static int composite_pread(BlockDriverState *bs, int64_t offset,
+               uint8_t *buf, int count)
+{
+    BDRVPartState *s = bs->opaque;
+    int ret,sstart,send,i;
+    int64_t sector_num, nb_sectors;
+
+    sector_num = offset / 512; /* integer division rounds down thankfully */
+    nb_sectors = (offset + count) / 512;
+    /* unfortunatly it won't round up so we have to check manually */
+    if (((offset + count) % 512) != 0)
+    {
+           nb_sectors ++;
+    }
+
+    sstart = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if ((s->slave_bs[i].start_sector +
+                           s->slave_bs[i].bs->total_sectors > sector_num)
+                           && (s->slave_bs[i].start_sector <= sector_num))
+           {
+                   sstart = i;
+                   break;
+           }
+    }
+    if (sstart == -1) return -1;
+
+    send = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
+                           > sector_num+nb_sectors)
+                           && (s->slave_bs[i].start_sector
+                           <= sector_num+nb_sectors))
+           {
+                   send = i;
+                   break;
+           }
+    }
+    if (send == -1) return -1;
+
+    if (sstart > send) return -2; //wtf???
+
+    int a = 0, bufpos = 0;
+
+    a = ((s->slave_bs[sstart].start_sector +
+                   s->slave_bs[sstart].bs->total_sectors) * 512) - offset;
+    if (a > count && sstart != send) return -3; //wtf??????
+    if (a > count) a = count;
+
+    ret = bdrv_pread(s->slave_bs[sstart].bs, offset - 
(s->slave_bs[sstart].start_sector*512), buf, a);
+    bufpos = bufpos + a;
+
+    if (ret != 0) return ret;
+    if (sstart == send) return ret; /* we're done */
+
+    i = sstart + 1;
+    while (i < send)
+    {
+           a = s->slave_bs[i].bs->total_sectors * 512;
+           ret = bdrv_pread(s->slave_bs[i].bs, 0, &(buf[bufpos]), a);
+           if (ret != 0) return ret;
+           bufpos = bufpos + a;
+           i++;
+    }
+    i= bdrv_pread(s->slave_bs[send].bs, 0, &(buf[bufpos]), count - bufpos);
+    return i;
+}
+
+static int composite_pwrite(BlockDriverState *bs, int64_t offset,
+               const uint8_t *buf, int count)
+{
+    BDRVPartState *s = bs->opaque;
+    int ret,sstart,send,i;
+    int64_t sector_num, nb_sectors;
+
+    sector_num = offset / 512; /* integer division rounds down thankfully */
+    nb_sectors = (offset + count) / 512;
+    /* unfortunatly it won't round up so we have to check manually */
+    if (((offset + count) % 512) != 0)
+    {
+           nb_sectors ++;
+    }
+
+    sstart = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if ((s->slave_bs[i].start_sector +
+                           s->slave_bs[i].bs->total_sectors > sector_num)
+                           && (s->slave_bs[i].start_sector <= sector_num))
+           {
+                   sstart = i;
+                   break;
+           }
+    }
+    if (sstart == -1) return -1;
+
+    send = -1;
+    for (i = 0; i < s->slave_count; i++)
+    {
+           if((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
+                           > sector_num+nb_sectors)
+                           && (s->slave_bs[i].start_sector
+                           <= sector_num+nb_sectors))
+           {
+                   send = i;
+                   break;
+           }
+    }
+    if (send == -1) return -1;
+
+    if (sstart > send) return -2; //wtf???
+
+    int a = 0, bufpos = 0;
+
+    a = ((s->slave_bs[sstart].start_sector +
+                   s->slave_bs[sstart].bs->total_sectors) * 512) - offset;
+    if (a > count && sstart != send) return -3; //wtf??????
+    if (a > count) a = count;
+
+    ret = bdrv_pwrite(s->slave_bs[sstart].bs, offset - 
(s->slave_bs[sstart].start_sector*512), buf, a);
+    bufpos = bufpos + a;
+
+    if (ret != 0) return ret;
+    if (sstart == send) return ret; /* we're done */
+
+    i = sstart + 1;
+    while (i < send)
+    {
+           a = s->slave_bs[i].bs->total_sectors * 512;
+           ret = bdrv_pwrite(s->slave_bs[i].bs, 0, &(buf[bufpos]), a);
+           if (ret != 0) return ret;
+           bufpos = bufpos + a;
+           i++;
+    }
+    i= bdrv_pwrite(s->slave_bs[send].bs, 0, &(buf[bufpos]), count - bufpos);
+    return i;
+}
+
+static void composite_aio_read_cb(void *opaque, int ret)
+{
+    CompositeAIOCB *acb = (CompositeAIOCB *)opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVPartState *s = bs->opaque;
+
+    acb->slave_aiocb = NULL;
+    if (ret < 0)
+    {
+    fail:
+           acb->common.cb(acb->common.opaque, ret);
+           qemu_aio_release(acb);
+           return;
+    }
+
+    acb->cur_sect += acb->slave_ret;
+    acb->buf += acb->slave_ret * 512;
+
+    if (acb->cur_sect >= acb->end_sect)
+    {
+           /* request completed */
+           acb->common.cb(acb->common.opaque, 0);
+           qemu_aio_release(acb);
+           return;
+    }
+    
+    acb->slave_cur += acb->slave_ret;
+
+    if (acb->slave_cur >= acb->slave_end)
+    {
+           acb->which_slave++;
+           acb->slave_start = 0;
+
+           acb->slave_end = s->slave_bs[acb->which_slave].bs->total_sectors;
+           if ((s->slave_bs[acb->which_slave].start_sector +
+                           s->slave_bs[acb->which_slave].bs->total_sectors) >
+                           acb->end_sect)
+               acb->slave_end = acb->end_sect -
+                       s->slave_bs[acb->which_slave].start_sector;
+
+           acb->slave_cur = acb->slave_start;
+    }
+
+    acb->slave_ret = acb->slave_end - acb->slave_cur;
+    acb->slave_aiocb = bdrv_aio_read(s->slave_bs[acb->which_slave].bs,
+                   acb->slave_cur, acb->buf, acb->slave_ret,
+                   composite_aio_read_cb, acb);
+    if (acb->slave_aiocb == NULL) goto fail;
+}
+
+static void composite_aio_write_cb(void * opaque, int ret)
+{
+    CompositeAIOCB *acb = (CompositeAIOCB *)opaque;
+    BlockDriverState *bs = acb->common.bs;
+    BDRVPartState *s = bs->opaque;
+
+    acb->slave_aiocb = NULL;
+    if (ret < 0)
+    {
+    fail:
+           acb->common.cb(acb->common.opaque, ret);
+           qemu_aio_release(acb);
+           return;
+    }
+
+    acb->cur_sect += acb->slave_ret;
+    acb->buf += acb->slave_ret * 512;
+
+    if (acb->cur_sect >= acb->end_sect)
+    {
+           acb->common.cb(acb->common.opaque, 0);
+           qemu_aio_release(acb);
+           return;
+    }
+    
+    acb->slave_cur += acb->slave_ret;
+
+    if (acb->slave_cur >= acb->slave_end)
+    {
+           acb->which_slave++;
+           acb->slave_start = 0;
+
+           acb->slave_end = s->slave_bs[acb->which_slave].bs->total_sectors;
+           if ((s->slave_bs[acb->which_slave].start_sector +
+                           s->slave_bs[acb->which_slave].bs->total_sectors) >
+                           acb->end_sect)
+               acb->slave_end = acb->end_sect -
+                       s->slave_bs[acb->which_slave].start_sector;
+
+           acb->slave_cur = acb->slave_start;
+    }
+
+    acb->slave_ret = acb->slave_end - acb->slave_cur;
+    acb->slave_aiocb = bdrv_aio_write(s->slave_bs[acb->which_slave].bs,
+                   acb->slave_cur, acb->buf, acb->slave_ret,
+                   composite_aio_write_cb, acb);
+    if (acb->slave_aiocb == NULL) goto fail;
+}
+
+static CompositeAIOCB * composite_aio_setup(BlockDriverState *bs,
+               int64_t sector_num, uint8_t *buf, int nb_sectors,
+               BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVPartState *s = bs->opaque;
+    CompositeAIOCB *acb;
+    int i;
+
+    acb = qemu_aio_get(bs, cb, opaque);
+    if (!acb) return NULL;
+
+    acb->start_sect = sector_num;
+    acb->end_sect = sector_num + nb_sectors;
+    acb->cur_sect = sector_num;
+    acb->buf = buf;
+    for (i = 0; i < s->slave_count; i ++)
+    {
+           if ((s->slave_bs[i].start_sector + s->slave_bs[i].bs->total_sectors
+                           > sector_num) && (s->slave_bs[i].start_sector <
+                                   sector_num))
+           {
+                   acb->which_slave = i;
+                   break;
+           }
+    }
+    acb->slave_start = sector_num - s->slave_bs[acb->which_slave].start_sector;
+    acb->slave_end = s->slave_bs[acb->which_slave].bs->total_sectors;
+    if ((s->slave_bs[acb->which_slave].start_sector +
+                   s->slave_bs[acb->which_slave].bs->total_sectors) >
+                   acb->end_sect)
+       acb->slave_end = acb->end_sect -
+               s->slave_bs[acb->which_slave].start_sector;
+    acb->slave_cur = acb->slave_start;
+    acb->slave_ret = 0;
+    acb->slave_aiocb = NULL;
+    return acb;
+}
+
+static BlockDriverAIOCB * composite_aio_read(BlockDriverState *bs,
+               int64_t sector_num, uint8_t *buf, int nb_sectors,
+               BlockDriverCompletionFunc *cb, void *opaque)
+{
+    CompositeAIOCB *acb;
+
+    acb = composite_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+    if (!acb) return NULL;
+
+    composite_aio_read_cb(acb, 0);
+    return &acb->common;
+}
+
+static BlockDriverAIOCB * composite_aio_write(BlockDriverState *bs,
+               int64_t sector_num, const uint8_t *buf, int nb_sectors,
+               BlockDriverCompletionFunc *cb, void *opaque)
+{
+    CompositeAIOCB *acb;
+
+    acb = composite_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, 
opaque);
+    if (!acb) return NULL;
+
+    composite_aio_write_cb(acb, 0);
+    return &acb->common;
+}
+
+static void composite_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+       CompositeAIOCB * acb = (CompositeAIOCB *)blockacb;
+       if (acb->slave_aiocb)
+               bdrv_aio_cancel(acb->slave_aiocb);
+       qemu_aio_release(acb);
+}
+
+static void composite_close(BlockDriverState *bs)
+{
+    BDRVPartState *s = bs->opaque;
+    int i;
+    for (i = 0; i < s->slave_count; i++)
+    {
+        bdrv_close(s->slave_bs[i].bs);
+        qemu_free(s->slave_bs[i].bs);
+    }
+    qemu_free(s->slave_bs);
+    s->slave_bs = NULL;
+}
+
+static int composite_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_composite = {
+    "composite",
+    sizeof(BDRVPartState),
+    composite_probe,
+    composite_open,
+    composite_read,
+    composite_write,
+    composite_close,
+    composite_create,
+    .bdrv_aio_read = composite_aio_read,
+    .bdrv_aio_write = composite_aio_write,
+    .bdrv_aio_cancel = composite_aio_cancel,
+    .aiocb_size = sizeof(CompositeAIOCB),
+
+    .protocol_name = "composite",
+    .bdrv_pread = composite_pread,
+    .bdrv_pwrite = composite_pwrite,
+};
+
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/block-partition.c qemu.notlast/block-partition.c
--- qemu/block-partition.c      Wed Dec 31 19:00:00 1969
+++ qemu.notlast/block-partition.c      Wed Mar  7 10:47:06 2007
@@ -0,0 +1,417 @@
+/*
+ * Block driver to use partitions as hard disks
+ * 
+ * Copyright (c) 2007 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.
+ */
+
+/* we need this in order to be able to figure out the sizes of the individual 
partitions */
+#include "block_composite.h"
+
+/* in sectors */
+#define MBR_SIZE 63
+
+/* ideally these would be dynamically allocated */
+#define MAX_PART_STRING 4096
+#define MAX_PARTS 10 /* probably only need 4 */
+
+typedef struct CompositeDriverState {
+    BlockDriverState * bs;
+} CompositeDriverState;
+
+static int partition_probe(const uint8_t *buf, int buf_size, const char 
*filename)
+{
+    if (strstart(filename, "partition:", NULL))
+        return 100;
+    return 0;
+}
+
+static int partition_setup(BlockDriverState *bs, const char *nfilename, int 
flags)
+{
+    CompositeDriverState *s;
+    BlockDriverState * bbs;
+    int64_t size, totalsectors;
+    int boot_fd, i, bootid = 1, partition_count = 0;
+    int head = 0, cylinder = 0, sector, oldstart;
+    int oldhead, oldcylinder, oldsector, origsector = 0;
+    int sysid[MAX_PARTS];
+    int64_t sectsizes[MAX_PARTS]; /* used only by writeout */
+    const char * zfilename = &(nfilename[10]), * nptr = zfilename;
+    char * filename, * strerr = NULL, * bootloader, * writeout = NULL;
+    char mbr_data[MBR_SIZE*512], partition_string[MAX_PART_STRING];
+    partition_string[0] = '\0';
+    if (bs != NULL)
+    s = bs->opaque;
+    else
+          s = NULL;
+
+    strcat(partition_string, "composite:ram:63,"); /*63 == MBR_SIZE */
+    bootloader = strdup("bootmbr.bin");
+    if (bs != NULL)
+    bs->read_only = 0;
+
+    int n = 0;
+    while (nptr != NULL)
+    {
+       nptr = strchr(zfilename, ',')+1;
+       if ((nptr-1) != NULL)
+       {
+               filename = strndup(zfilename, (size_t)((nptr-1)-zfilename));
+               zfilename = nptr;
+       }
+       else
+       {
+               filename = strdup(zfilename);
+               nptr = NULL;
+       }
+
+       if (strncmp(filename, "sysid=", 6) == 0)
+       {
+               /* just pass in any sysid, e.g. 0x82 or 0x0C */
+               char ffd[strlen(filename)];
+               ffd[0] = ' ';
+               ffd[1] = '\0';
+               strcat(ffd, filename+6);
+               sysid[partition_count-1] = (int)strtol(ffd, &strerr, 0);
+
+               if (*strerr != '\0') /* detect error in conversion */
+                       sysid[partition_count-1] = 0x0C; /* default to win98 
FAT32 */
+       }
+       else if (strncmp(filename, "boot=", 5) == 0)
+       {
+               /* between 1 and 4, 1 selects the first partition, 4 selects 
the last partition (if you are making a hard disk with 4 partitions in it) */
+               char ffd[strlen(filename)];
+               int bootidf;
+               ffd[0] = ' ';
+               ffd[1] = '\0';
+               strcat(ffd, filename+5);
+               bootidf = (int)strtol(ffd, &strerr, 0);
+
+               if (*strerr == '\0') /* no detect error in conversion */
+                       bootid = bootidf;
+       }
+       else if (strncmp(filename, "bootloader=", 11) == 0)
+       {
+               free(bootloader);
+               bootloader = strdup(filename+11);
+       }
+       else if (strncmp(filename, "out=", 4) == 0)
+       {
+               /* perhaps a warning if out=file.img was passed to 
partition_open() ? */
+               /* if multiple out= s are given we use the last one - perhaps 
we should warn when we do this? */
+               if (writeout != NULL) free(writeout);
+               writeout = strdup(filename+4);
+       }
+       else
+       {
+               /* the string shouldn't start with a ',' */
+               if (n)
+                       strcat(partition_string, ",");
+               else
+                       n = 1;
+
+               strcat(partition_string, filename);
+               partition_count ++;
+               sysid[partition_count-1] = 0x0C; /* default to win98 FAT32 */
+               if (s == NULL)
+               {
+                       int fd = open(filename, O_RDONLY);
+                       if (fd == -1)
+                       {
+                               free(bootloader);
+                               if (writeout != NULL) free(writeout);
+                               return -1;
+                       }
+                       int64_t ssized = lseek(fd, 0, SEEK_END);
+                       close(fd);
+                       sectsizes[partition_count-1] = ssized;
+               }
+       }
+       free(filename);
+    }
+
+    if (s != NULL)
+    {
+
+    s->bs = qemu_mallocz(sizeof(BlockDriverState));
+    if ((s->bs == NULL) || (bdrv_open2(s->bs, partition_string, 0, NULL) != 0))
+    {
+           free(bootloader);
+           if (writeout != NULL) free(writeout);
+           return -1;
+    }
+
+    bs->total_sectors = s->bs->total_sectors;
+    bs->read_only = s->bs->read_only;
+
+    }
+
+    /* get the fake MBR */
+    memset(mbr_data, 0, MBR_SIZE*512);
+    boot_fd = open(bootloader, O_RDONLY);
+    if (boot_fd == -1)
+    {
+           printf("Warning: failed to open bootmbr.bin - MBR will not be 
bootable\n");
+    }
+    else
+    {
+           if (read(boot_fd, mbr_data, MBR_SIZE*512) == -1)
+           {
+               printf("Warning: failed to read bootmbr.bin - MBR will not be 
bootable\n");
+           }
+           close(boot_fd);
+    }
+
+    oldstart = 0x3F; //3F == 63
+    oldhead = 0x01;
+    oldsector = 0x01;
+    oldcylinder = 0x00;
+
+    for (i = 0; i < partition_count; i++)
+    {
+
+    /* set up c/h/s */
+    if (bs != NULL)
+    {
+
+    /*if (i == partition_count-1)
+    {
+    totalsectors = bs->total_sectors;
+    }
+    else
+    {*/
+    /* remember that the very first slave in the composite is the ram image **
+     * that we're using to store the MBR, so the second slave in the composite
+     * is the first partition */
+    bbs = ((BDRVPartState*)s->bs->opaque)->slave_bs[i+1].bs;
+    totalsectors = bbs->total_sectors;
+    /*}*/
+
+    }
+    else
+    {
+           totalsectors = sectsizes[i] / 512;
+    }
+
+    /*size = totalsectors * 512;*/
+    size = oldstart * 512;
+    origsector += totalsectors;
+    while (origsector > 63)
+    {
+           origsector -= 63;
+           head += 1;
+           while (head > 16)
+           {
+                   head -= 16;
+                   cylinder += 1;
+           }
+    }
+    /*
+    cylinder = size/(63*16);
+    head = 16;
+    sector = 63;
+    */
+    /* some bit twiddling here */
+    sector = (((cylinder >> 8) & 3) << 6) + origsector;
+
+    /* set up fake MBR - each partition entry is 16 bytes long */
+    /* start 446 */
+    /* set which partition is meant to be bootable (that we'll boot from) */
+    if (i == bootid)
+    mbr_data[446+((i-1)*16)] = 0x80;
+    else
+    mbr_data[446+((i-1)*16)] = 0x00;
+    /* start head */
+    mbr_data[447+((i-1)*16)] = oldhead;
+    /* start sector - only first 6 bits */
+    mbr_data[448+((i-1)*16)] = oldsector;
+    /* start cylinder - this byte plus 2 bits from mbr_data[447] */
+    mbr_data[449+((i-1)*16)] = oldcylinder;
+    /* system ID */
+    mbr_data[450+((i-1)*16)] = sysid[i-1];
+    /* ending head */
+    mbr_data[451+((i-1)*16)] = head;
+    /* ending sector */
+    mbr_data[452+((i-1)*16)] = sector;
+    /* ending cylinder */
+    mbr_data[453+((i-1)*16)] = cylinder;
+    /* absolute start sector - 4 bytes/DWORD */
+    //mbr_data[454+(i*16)] = 0x3F; // 3F = 63
+    *((uint32_t*)(mbr_data+454+((i-1)*16))) = cpu_to_le32(oldstart);
+    /* absolute total number of sectors - 4 bytes/DWORD */
+    *((uint32_t*)(mbr_data+458+((i-1)*16))) = cpu_to_le32(totalsectors);
+    /* end 462 */
+
+    oldstart = oldstart + totalsectors;
+    oldhead = head;
+    oldcylinder = cylinder;
+    oldsector = origsector;
+
+    int origoldsector = origsector;
+    origoldsector++;
+    if (origoldsector > 63)
+    {
+           oldhead++;
+           origoldsector = 0x01;
+           if (oldhead > 16)
+           {
+                   oldcylinder++;
+                   oldhead = 0x01;
+           }
+    }
+    /* some more bit twiddling here */
+    oldsector = (((cylinder >> 8) & 3) << 6) + origoldsector;
+
+    }
+
+    /* set the MBR sector signature */
+    mbr_data[510] = 0x55;
+    mbr_data[511] = 0xAA;
+
+    /* now write it to the ram image */
+    /*
+    bs->boot_sector_enabled = 0;
+    s->bs->boot_sector_enabled = 0;
+    bbs = ((BDRVPartState*)s->bs->opaque)->slave_bs[0].bs; the ram image
+    bbs->boot_sector_enabled = 0;
+    */
+    if (s != NULL)
+    {
+           if (bdrv_write(s->bs, 0, mbr_data, MBR_SIZE) != 0)
+           printf("Warning: failed to commit MBR and partition table to fake 
hard disk\n");
+
+           bdrv_set_boot_sector(bs, mbr_data, 512);
+           bdrv_set_boot_sector(s->bs, mbr_data, 512);
+           
bdrv_set_boot_sector(((BDRVPartState*)s->bs->opaque)->slave_bs[0].bs , 
mbr_data, 512);
+    }
+    else if (s == NULL)
+    {
+           /* write mbr_data to writeout (specified by out=file.img) */
+           int fd = open(writeout, O_WRONLY | O_TRUNC);
+           if (fd == -1)
+           {
+               if (writeout != NULL) free(writeout);
+               return -1;
+           }
+           /* FIXME XXX check for errors on write! */
+           write(fd, mbr_data, MBR_SIZE*512);
+           close(fd);
+    }
+    if (writeout != NULL) free(writeout);
+
+    return 0;
+}
+
+static int partition_open(BlockDriverState *bs, const char *nfilename, int 
flags)
+{
+    return partition_setup(bs, nfilename, flags);
+}
+
+static int partition_read(BlockDriverState *bs, int64_t sector_num, 
+                    uint8_t *buf, int nb_sectors)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_read(s->bs, sector_num, buf, nb_sectors);
+}
+
+static int partition_write(BlockDriverState *bs, int64_t sector_num, 
+                     const uint8_t *buf, int nb_sectors)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_write(s->bs, sector_num, buf, nb_sectors);
+}
+
+static int partition_pread(BlockDriverState *bs, int64_t offset, 
+                    uint8_t *buf, int count)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_pread(s->bs, offset, buf, count);
+}
+
+static int partition_pwrite(BlockDriverState *bs, int64_t offset, 
+                     const uint8_t *buf, int count)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_pwrite(s->bs, offset, buf, count);
+}
+
+static BlockDriverAIOCB* partition_aio_read(BlockDriverState *bs,
+               int64_t sector_num, uint8_t *buf, int nb_sectors,
+               BlockDriverCompletionFunc *cb, void *opaque)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_aio_read(s->bs, sector_num, buf, nb_sectors, cb, opaque);
+}
+
+static BlockDriverAIOCB* partition_aio_write(BlockDriverState *bs,
+               int64_t sector_num, const uint8_t *buf, int nb_sectors,
+               BlockDriverCompletionFunc *cb, void *opaque)
+{
+    CompositeDriverState *s = bs->opaque;
+    return bdrv_aio_write(s->bs, sector_num, buf, nb_sectors, cb, opaque);
+}
+
+static void partition_aio_cancel(BlockDriverAIOCB *acb)
+{
+    /* This function will never get called - since aio requests are **
+     * shoved off to the composite driver, the acbs are set up with the **
+     * set of Composite callbacks, including composite_aio_cancel */
+
+    /*CompositeDriverState *s = acb->bs->opaque;
+    bdrv_aio_cancel(acb);*/
+    printf("Warning: partition_aio_cancel is not suppose to be called... get 
help. NOW!\n");
+}
+
+static void partition_close(BlockDriverState *bs)
+{
+    CompositeDriverState *s = bs->opaque;
+    bdrv_close(s->bs);
+    qemu_free(s->bs);
+    s->bs = NULL;
+}
+
+static int partition_create(const char *filename, int64_t total_size,
+                      const char *backing_file, int flags)
+{
+    /* FIXME XXX right now we ignore the requested size of the file */
+    return partition_setup(NULL, filename, flags);
+}
+
+BlockDriver bdrv_partition = {
+    "partition",
+    sizeof(CompositeDriverState),
+    partition_probe,
+    partition_open,
+    //partition_read,
+    NULL,
+    //partition_write,
+    NULL,
+    partition_close,
+    partition_create,
+    .bdrv_aio_read = partition_aio_read,
+    .bdrv_aio_write = partition_aio_write,
+    .bdrv_aio_cancel = partition_aio_cancel,
+    .aiocb_size = sizeof(CompositeAIOCB),
+
+    .protocol_name = "partition",
+    .bdrv_pread = partition_pread,
+    .bdrv_pwrite = partition_pwrite,
+};
+
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/block-ram.c qemu.notlast/block-ram.c
--- qemu/block-ram.c    Wed Dec 31 19:00:00 1969
+++ qemu.notlast/block-ram.c    Tue Mar  6 15:57:09 2007
@@ -0,0 +1,109 @@
+/*
+ * Block driver in RAM
+ * 
+ * Copyright (c) 2007 Jim Boown
+ * 
+ * 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"
+#include <assert.h>
+
+#ifndef QEMU_TOOL
+#include "exec-all.h"
+#endif
+
+typedef struct BDRVRamState {
+    char * ram_data;
+} BDRVRamState;
+
+static int ram_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+    if (strstart(filename, "ram:", NULL))
+           return 100;
+    return 0;
+}
+static int ram_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRamState *s = bs->opaque;
+
+    if (!strstart(filename, "ram:", NULL))
+           return -1;
+
+    int sectnum = atoi(filename+4);
+    if (sectnum == 0) return -2;
+
+    s->ram_data = qemu_mallocz(sectnum*512);
+    if (s->ram_data == NULL) return -2;
+    memset(s->ram_data, ' ', sectnum*512);
+
+    bs->total_sectors = sectnum;
+    return 0;
+}
+
+static int ram_read(BlockDriverState *bs, int64_t sector_num, 
+                     uint8_t *buf, int nb_sectors)
+{
+    BDRVRamState *s = bs->opaque;
+    if (sector_num+nb_sectors > bs->total_sectors)
+               return -1;
+    memcpy(buf, &(s->ram_data[sector_num*512]), nb_sectors*512);
+    return 0;
+}
+
+static int ram_write(BlockDriverState *bs, int64_t sector_num, 
+                      const uint8_t *buf, int nb_sectors)
+{
+    BDRVRamState *s = bs->opaque;
+    if (sector_num+nb_sectors > bs->total_sectors)
+               return -1;
+    memcpy(&(s->ram_data[sector_num*512]), buf, nb_sectors*512);
+    return 0;
+}
+
+static void ram_close(BlockDriverState *bs)
+{
+    BDRVRamState *s = bs->opaque;
+    qemu_free(s->ram_data);
+}
+
+static int ram_is_allocated(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, int* n)
+{
+    *n = bs->total_sectors - sector_num;
+    if (*n > nb_sectors)
+        *n = nb_sectors;
+    else if (*n < 0)
+        return 0;
+    return 1;
+}
+
+BlockDriver bdrv_ram = {
+    "ram",
+    sizeof(BDRVRamState),
+    ram_probe,
+    ram_open,
+    ram_read,
+    ram_write,
+    ram_close,
+    NULL,
+    NULL,
+    ram_is_allocated,
+   .protocol_name = "ram",
+};
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/block.c qemu.notlast/block.c
--- qemu/block.c        Sun Feb 11 10:06:09 2007
+++ qemu.notlast/block.c        Wed Mar  7 10:29:57 2007
@@ -1241,6 +1241,9 @@
     bdrv_register(&bdrv_vpc);
     bdrv_register(&bdrv_vvfat);
     bdrv_register(&bdrv_qcow2);
+    bdrv_register(&bdrv_composite);
+    bdrv_register(&bdrv_ram);
+    bdrv_register(&bdrv_partition);
 }
 
 void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* 
qemu/block_composite.h qemu.notlast/block_composite.h
--- qemu/block_composite.h      Wed Dec 31 19:00:00 1969
+++ qemu.notlast/block_composite.h      Tue Mar  6 10:58:31 2007
@@ -0,0 +1,54 @@
+/*
+ * Block driver to use composite images
+ * 
+ * Copyright (c) 2007 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.
+ */
+#ifndef BLOCK_COMPOSITE_H
+#define BLOCK_COMPOSITE_H
+
+#include "vl.h"
+#include "block_int.h"
+
+typedef struct SlaveDriverState {
+    BlockDriverState * bs;
+    int start_sector;
+} SlaveDriverState;
+
+typedef struct BDRVPartState {
+    SlaveDriverState * slave_bs;
+    int slave_count;
+} BDRVPartState;
+
+typedef struct CompositeAIOCB {
+    BlockDriverAIOCB common;
+    int64_t start_sect;
+    int64_t end_sect;
+    int64_t cur_sect;
+    uint8_t *buf;
+    int which_slave;
+    int64_t slave_start;
+    int64_t slave_end;
+    int64_t slave_cur;
+    int slave_ret;
+    BlockDriverAIOCB *slave_aiocb;
+} CompositeAIOCB;
+
+#endif /*BLOCK_COMPOSITE_H*/
diff -ur --new-file --exclude=.#* --exclude=*CVS* --exclude=*gen-op* 
--exclude=block-composite1.c --exclude=*config* --exclude=*-softmmu* qemu/vl.h 
qemu.notlast/vl.h
--- qemu/vl.h   Tue Mar  6 18:52:01 2007
+++ qemu.notlast/vl.h   Wed Mar  7 10:30:03 2007
@@ -557,6 +557,9 @@
 extern BlockDriver bdrv_vpc;
 extern BlockDriver bdrv_vvfat;
 extern BlockDriver bdrv_qcow2;
+extern BlockDriver bdrv_composite;
+extern BlockDriver bdrv_ram;
+extern BlockDriver bdrv_partition;
 
 typedef struct BlockDriverInfo {
     /* in bytes, 0 if irrelevant */
--- hw/pc.c     Mon Mar  5 14:44:02 2007
+++ hw/pc.c     Wed Mar  7 13:37:37 2007
@@ -42,6 +42,24 @@
 static IOAPICState *ioapic;
 static PCIDevice *i440fx_state;
 
+#define LINUX_BOOT_TIME 1000
+static QEMUTimer *linux_boot_timer;
+static void linux_boot_cleanup(void *opaque)
+{
+       if (opaque == NULL)
+       {
+               /* using ram bs */
+               bdrv_close(fd_table[0]);
+       }
+       else
+       {
+               /* there is a real floppy underneath */
+               bdrv_set_boot_sector(fd_table[0], opaque, 512);
+               qemu_free(opaque);
+       }
+       qemu_free_timer(linux_boot_timer);
+}
+
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
 }
@@ -457,6 +475,7 @@
     int piix3_devfn = -1;
     CPUState *env;
     NICInfo *nd;
+    int using_ram_bs = 0;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -566,10 +585,10 @@
 
     if (linux_boot) {
         uint8_t bootsect[512];
-        uint8_t old_bootsect[512];
+        uint8_t *old_bootsect = NULL;
 
-        if (bs_table[0] == NULL) {
-            fprintf(stderr, "A disk image must be given for 'hda' when booting 
a Linux kernel\n");
+        if (fd_table[0] == NULL) {
+            fprintf(stderr, "This should never happen!\n");
             exit(1);
         }
         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
@@ -580,12 +599,29 @@
             exit(1);
         }
 
-        if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
-            /* copy the MSDOS partition table */
-            memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
+       old_bootsect = qemu_mallocz(512);
+       if (old_bootsect == NULL)
+       {
+            fprintf(stderr, "qemu: not enough ram to allocate 512 bytes\n");
+            exit(1);
+       }
+        if (bdrv_read(fd_table[0], 0, old_bootsect, 1) >= 0) {
+           using_ram_bs = 0;
+        } else {
+           using_ram_bs = 1;
+           if (bdrv_open(fd_table[0], "ram:63", 0) < 0)
+           {
+                   printf("Another thing which should never happen, 
happened..\n");
+                   exit(1);
+           }
+           qemu_free(old_bootsect);
+           old_bootsect = NULL;
         }
 
-        bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
+        bdrv_set_boot_sector(fd_table[0], bootsect, sizeof(bootsect));
+       /* implied by using a kernel boot */
+       boot_device = 'a';
+       fd_bootchk = 0;
 
         /* now we can load the kernel */
         ret = load_kernel(kernel_filename, 
@@ -618,6 +654,11 @@
                 KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
         /* loader type */
         stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
+
+       linux_boot_timer = qemu_new_timer(rt_clock, linux_boot_cleanup,
+                       using_ram_bs ? NULL : old_bootsect);
+       qemu_mod_timer(linux_boot_timer, qemu_get_clock(rt_clock) +
+                       LINUX_BOOT_TIME);
     }
 
     if (pci_enabled) {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]