Patchwork Port codes from qemu-kvm to support boot from SCSI image

login
register
mail settings
Submitter Haishan Bai
Date Aug. 17, 2010, 3:59 p.m.
Message ID <4C6AB1F1.1020306@gmail.com>
Download mbox | patch
Permalink /patch/61927/
State New
Headers show

Comments

Haishan Bai - Aug. 17, 2010, 3:59 p.m.
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
malc - Aug. 17, 2010, 6:57 p.m.
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, &sectors);
> +    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 */ }
>      },
>
Haishan Bai - Aug. 18, 2010, 1:39 a.m.
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, &sectors);
>> +    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
Haishan Bai - Aug. 18, 2010, 3:32 a.m.
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, &sectors);
>> +    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
malc - Aug. 18, 2010, 3:43 a.m.
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.
Haishan Bai - Aug. 18, 2010, 3:47 a.m.
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.
>
>
malc - Aug. 18, 2010, 4:02 a.m.
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.

Patch

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, &sectors);
+    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 */ }
      },