On Tue, 17 Aug 2010, Haishan Bai wrote: > Port codes from qemu-kvm to support boot from SCSI image > > Signed-off-by: Shan Hai <haishan....@gmail.com> > --- > Makefile.target | 1 + > blockdev.c | 13 ++++++ > blockdev.h | 2 + > hw/extboot.c | 123 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/ivshmem.c | 2 +- > hw/pc.c | 17 ++++++++ > hw/pc.h | 4 ++ > qemu-config.c | 4 ++ > 8 files changed, 165 insertions(+), 1 deletions(-) > create mode 100644 hw/extboot.c > > diff --git a/Makefile.target b/Makefile.target > index c8281e9..abba79c 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -199,6 +199,7 @@ obj-i386-y += mc146818rtc.o i8259.o pc.o > obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o > obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o > obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o > +obj-i386-y += extboot.o > obj-i386-y += debugcon.o multiboot.o > obj-i386-y += pc_piix.o > > diff --git a/blockdev.c b/blockdev.c > index 01e402b..78c286c 100644 > --- a/blockdev.c > +++ b/blockdev.c > @@ -15,6 +15,8 @@ > #include "qemu-config.h" > #include "sysemu.h" > > +DriveInfo *extboot_drive = NULL; > + > static QTAILQ_HEAD(drivelist, DriveInfo) drives = > QTAILQ_HEAD_INITIALIZER(drives); > > /* > @@ -150,6 +152,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, > int *fatal_error) > int on_read_error, on_write_error; > const char *devaddr; > DriveInfo *dinfo; > + int is_extboot = 0; > int snapshot = 0; > int ret; > > @@ -311,6 +314,12 @@ DriveInfo *drive_init(QemuOpts *opts, int > default_to_scsi, int *fatal_error) > } > } > > + is_extboot = qemu_opt_get_bool(opts, "boot", 0); > + if (is_extboot && extboot_drive) { > + fprintf(stderr, "qemu: two bootable drives specified\n"); > + return NULL; > + } > + > on_write_error = BLOCK_ERR_STOP_ENOSPC; > if ((buf = qemu_opt_get(opts, "werror")) != NULL) { > if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != > IF_NONE) { > @@ -421,6 +430,10 @@ DriveInfo *drive_init(QemuOpts *opts, int > default_to_scsi, int *fatal_error) > strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1); > QTAILQ_INSERT_TAIL(&drives, dinfo, next); > > + if (is_extboot) { > + extboot_drive = dinfo; > + } > + > bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error); > > switch(type) { > diff --git a/blockdev.h b/blockdev.h > index 37f3a01..e707b87 100644 > --- a/blockdev.h > +++ b/blockdev.h > @@ -59,4 +59,6 @@ int do_block_set_passwd(Monitor *mon, const QDict *qdict, > QObject **ret_data); > int do_change_block(Monitor *mon, const char *device, > const char *filename, const char *fmt); > > +extern DriveInfo *extboot_drive; > + > #endif > diff --git a/hw/extboot.c b/hw/extboot.c > new file mode 100644 > index 0000000..8ada21b > --- /dev/null > +++ b/hw/extboot.c > @@ -0,0 +1,123 @@ > +/* > + * Extended boot option ROM support. > + * > + * Copyright IBM, Corp. 2007 > + * > + * Authors: > + * Anthony Liguori <aligu...@us.ibm.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > + > +#include "hw.h" > +#include "pc.h" > +#include "isa.h" > +#include "block.h" > + > +/* Extended Boot ROM suport */ > + > +union extboot_cmd > +{ > + uint16_t type; > + struct { > + uint16_t type; > + uint16_t cylinders; > + uint16_t heads; > + uint16_t sectors; > + uint64_t nb_sectors; > + } query_geometry; > + struct { > + uint16_t type; > + uint16_t nb_sectors; > + uint16_t segment; > + uint16_t offset; > + uint64_t sector; > + } xfer; > +};
What's with the indentation here? > + > +static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s) > +{ > + bdrv_get_geometry_hint(bs, c, h, s); > + > + if (*c <= 1024) { > + *c >>= 0; > + *h <<= 0; > + } else if (*c <= 2048) { > + *c >>= 1; > + *h <<= 1; > + } else if (*c <= 4096) { > + *c >>= 2; > + *h <<= 2; > + } else if (*c <= 8192) { > + *c >>= 3; > + *h <<= 3; > + } else { > + *c >>= 4; > + *h <<= 4; > + } > + > + /* what is the correct algorithm for this?? */ > + if (*h == 256) { > + *h = 255; > + *c = *c + 1; > + } > +} And here. > + > +static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value) > +{ > + union extboot_cmd cmd; > + BlockDriverState *bs = opaque; > + int cylinders, heads, sectors, err; > + uint64_t nb_sectors; > + target_phys_addr_t pa = 0; > + int blen = 0; > + void *buf = NULL; > + > + cpu_physical_memory_read((value & 0xFFFF) << 4, (uint8_t *)&cmd, > + sizeof(cmd)); > + > + if (cmd.type == 0x01 || cmd.type == 0x02) { > + pa = cmd.xfer.segment * 16 + cmd.xfer.offset; > + blen = cmd.xfer.nb_sectors * 512; > + buf = qemu_memalign(512, blen); > + } And here. > + > + switch (cmd.type) { > + case 0x00: > + get_translated_chs(bs, &cylinders, &heads, §ors); > + bdrv_get_geometry(bs, &nb_sectors); > + cmd.query_geometry.cylinders = cylinders; > + cmd.query_geometry.heads = heads; > + cmd.query_geometry.sectors = sectors; > + cmd.query_geometry.nb_sectors = nb_sectors; > + break; > + case 0x01: > + err = bdrv_read(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors); > + if (err) > + printf("Read failed\n"); > + > + cpu_physical_memory_write(pa, buf, blen); > + > + break; > + case 0x02: > + cpu_physical_memory_read(pa, buf, blen); > + > + err = bdrv_write(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors); > + if (err) > + printf("Write failed\n"); > + > + break; > + } And here. > + > + cpu_physical_memory_write((value & 0xFFFF) << 4, (uint8_t *)&cmd, > + sizeof(cmd)); > + if (buf) > + qemu_free(buf); > +} > + > +void extboot_init(BlockDriverState *bs) > +{ > + register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs); > +} > diff --git a/hw/ivshmem.c b/hw/ivshmem.c > index bbb5cba..e38ac2a 100644 > --- a/hw/ivshmem.c > +++ b/hw/ivshmem.c > @@ -353,7 +353,7 @@ static int check_shm_size(IVShmemState *s, int fd) { > if (s->ivshmem_size > buf.st_size) { > fprintf(stderr, "IVSHMEM ERROR: Requested memory size greater"); > fprintf(stderr, " than shared object size (%" PRIu64 " > %ld)\n", > - s->ivshmem_size, buf.st_size); > + s->ivshmem_size, (long int)buf.st_size); > return -1; > } else { > return 0; > diff --git a/hw/pc.c b/hw/pc.c > index 58dea57..88f43aa 100644 > --- a/hw/pc.c > +++ b/hw/pc.c > @@ -54,6 +54,7 @@ > #endif > > #define BIOS_FILENAME "bios.bin" > +#define EXTBOOT_FILENAME "extboot.bin" > > #define PC_MAX_BIOS_SIZE (4 * 1024 * 1024) > > @@ -953,6 +954,10 @@ void pc_memory_init(ram_addr_t ram_size, > isa_bios_size, > (bios_offset + bios_size - isa_bios_size) | > IO_MEM_ROM); > > + if (extboot_drive) { > + option_rom[nb_option_roms++] = qemu_strdup(EXTBOOT_FILENAME); > + } > + > option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE); > cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, > option_rom_offset); > > @@ -1074,4 +1079,16 @@ void pc_pci_device_init(PCIBus *pci_bus) > for (bus = 0; bus <= max_bus; bus++) { > pci_create_simple(pci_bus, -1, "lsi53c895a"); > } > + > + if (extboot_drive) { > + DriveInfo *info = extboot_drive; > + int cyls, heads, secs; > + > + if (info->type != IF_IDE && info->type != IF_VIRTIO) { > + bdrv_guess_geometry(info->bdrv, &cyls, &heads, &secs); > + bdrv_set_geometry_hint(info->bdrv, cyls, heads, secs); > + } > + > + extboot_init(info->bdrv); > + } > } > diff --git a/hw/pc.h b/hw/pc.h > index 63b0249..61882db 100644 > --- a/hw/pc.h > +++ b/hw/pc.h > @@ -167,6 +167,10 @@ void isa_cirrus_vga_init(void); > > void isa_ne2000_init(int base, int irq, NICInfo *nd); > > +/* extboot.c */ > + > +void extboot_init(BlockDriverState *bs); > + > /* e820 types */ > #define E820_RAM 1 > #define E820_RESERVED 2 > diff --git a/qemu-config.c b/qemu-config.c > index 95abe61..0f3c775 100644 > --- a/qemu-config.c > +++ b/qemu-config.c > @@ -79,6 +79,10 @@ QemuOptsList qemu_drive_opts = { > },{ > .name = "readonly", > .type = QEMU_OPT_BOOL, > + },{ > + .name = "boot", > + .type = QEMU_OPT_BOOL, > + .help = "make this a boot drive", > }, > { /* end if list */ } > }, > -- mailto:av1...@comtv.ru