All of lore.kernel.org
 help / color / mirror / Atom feed
From: Haishan Bai <haishan.bai@gmail.com>
To: qemu-devel@nongnu.org
Cc: haishan.bai@gmail.com
Subject: [Qemu-devel] [PATCH] Port codes from qemu-kvm to support boot from SCSI image
Date: Tue, 17 Aug 2010 23:59:45 +0800	[thread overview]
Message-ID: <4C6AB1F1.1020306@gmail.com> (raw)

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;
+};
+
+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 */ }
      },
-- 
1.7.0.4

             reply	other threads:[~2010-08-17 16:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-17 15:59 Haishan Bai [this message]
2010-08-17 18:57 ` [Qemu-devel] [PATCH] Port codes from qemu-kvm to support boot from SCSI image malc
2010-08-18  1:39   ` haishan
2010-08-18  3:32   ` haishan
2010-08-18  3:43     ` malc
2010-08-18  3:47       ` haishan
2010-08-18  4:02         ` malc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4C6AB1F1.1020306@gmail.com \
    --to=haishan.bai@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.