Message ID | 4C6AB1F1.1020306@gmail.com |
---|---|
State | New |
Headers | show |
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.bai@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 <aliguori@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 */ } > }, >
malc wrote: > 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.bai@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 <aliguori@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 */ } >> }, >> >> > > I am sorry about that, I will send V2, and believe me this will never can happen. Best regards Shan Hai
malc wrote: > 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.bai@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 <aliguori@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 */ } >> }, >> >> > > BTW, I am just curious why I can not receive what I have sent to the list? Best regards Shan Hai
On Wed, 18 Aug 2010, haishan wrote: > malc wrote: > > On Tue, 17 Aug 2010, Haishan Bai wrote: > > [..snip..] > > BTW, I am just curious why I can not receive what I have sent to the list? > Because you overquote. Beats me if that is not the real reason though.
malc wrote: > On Wed, 18 Aug 2010, haishan wrote: > > >> malc wrote: >> >>> On Tue, 17 Aug 2010, Haishan Bai wrote: >>> >>> > > [..snip..] > > >> BTW, I am just curious why I can not receive what I have sent to the list? >> >> > > Because you overquote. > > What did you mean by "overquote"? I am new in this list and have lots of troubles about mailing list, so tried several times and found out sent out several same posts, that's scary. Regards Shan Hai > Beats me if that is not the real reason though. > >
On Wed, 18 Aug 2010, haishan wrote: > malc wrote: > > On Wed, 18 Aug 2010, haishan wrote: > > > > > > > malc wrote: > > > > > > > On Tue, 17 Aug 2010, Haishan Bai wrote: > > > > > > > > > > > > [..snip..] > > > > > > > BTW, I am just curious why I can not receive what I have sent to the list? > > > > > > > > > > Because you overquote. > > > > > > What did you mean by "overquote"? I am new in this list and have lots of > troubles about mailing list, so tried several times and found out sent > out several same posts, that's scary. It was an attempt at humor, you posted your entire patch (see above, i've instead added a placeholder for irrelevant text) Back to your question: i've no idea.
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 <aliguori@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; +}; + +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; + } +} + +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); + } + + 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; + } + + 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 */ } },
Port codes from qemu-kvm to support boot from SCSI image Signed-off-by: Shan Hai <haishan.bai@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