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 + +#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 */