[Top][All Lists]
[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) {
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] [RFC] aio update for composite and partition block drivers and a fix for -kernel boot,
jma5 <=