From: Anthony Liguori <[EMAIL PROTECTED]>

This patch adds support to QEMU for extboot.  It requires that an extboot.bin
binary be copied into the pc-bios directory or else make install will not
function properly.

To use extboot to boot from an arbitrary block device, simply append a
",boot=on" to the block device to boot from.  For instance, to boot from a SCSI
disk, one would use:

 -drive file=/path/to/image.img,if=scsi,boot=on

Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]>
Signed-off-by: Avi Kivity <[EMAIL PROTECTED]>

diff --git a/qemu/Makefile b/qemu/Makefile
index ce76352..a3c6870 100644
--- a/qemu/Makefile
+++ b/qemu/Makefile
@@ -179,7 +179,7 @@ endif
        mkdir -p "$(DESTDIR)$(datadir)"
        for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
                video.x openbios-sparc32 pxe-ne2k_pci.bin \
-               pxe-rtl8139.bin pxe-pcnet.bin; do \
+               pxe-rtl8139.bin pxe-pcnet.bin extboot.bin; do \
                $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x 
"$(DESTDIR)$(datadir)"; \
        done
 ifndef CONFIG_WIN32
@@ -281,6 +281,7 @@ tarbin:
         $(datadir)/pxe-ne2k_pci.bin \
        $(datadir)/pxe-rtl8139.bin \
         $(datadir)/pxe-pcnet.bin \
+       $(datadir)/extboot.bin \
        $(docdir)/qemu-doc.html \
        $(docdir)/qemu-tech.html \
        $(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
diff --git a/qemu/Makefile.target b/qemu/Makefile.target
index 0c5ca47..289cd18 100644
--- a/qemu/Makefile.target
+++ b/qemu/Makefile.target
@@ -471,7 +471,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-VL_OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o
+VL_OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o
 CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
 endif
 ifeq ($(TARGET_BASE_ARCH), ia64)
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 5a1b7d4..aa9e16e 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -43,6 +43,7 @@ extern int kvm_allowed;
 #define BIOS_FILENAME "bios.bin"
 #define VGABIOS_FILENAME "vgabios.bin"
 #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
+#define EXTBOOT_FILENAME "extboot.bin"
 
 /* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
 #define ACPI_DATA_SIZE       0x10000
@@ -715,6 +716,37 @@ extern kvm_context_t kvm_context;
 extern int kvm_allowed;
 #endif
 
+static int load_option_rom(const char *filename, int offset)
+{
+    ram_addr_t option_rom_offset;
+    int size, ret;
+
+    size = get_image_size(filename);
+    if (size < 0) {
+       fprintf(stderr, "Could not load option rom '%s'\n", filename);
+       exit(1);
+    }
+    if (size > (0x10000 - offset))
+       goto option_rom_error;
+    option_rom_offset = qemu_ram_alloc(size);
+    ret = load_image(filename, phys_ram_base + option_rom_offset);
+    if (ret != size) {
+    option_rom_error:
+       fprintf(stderr, "Too many option ROMS\n");
+       exit(1);
+    }
+    size = (size + 4095) & ~4095;
+    cpu_register_physical_memory(0xd0000 + offset,
+                                size, option_rom_offset | IO_MEM_ROM);
+#ifdef USE_KVM
+    if (kvm_allowed)
+           kvm_cpu_register_physical_memory(0xd0000 + offset,
+                                             size, option_rom_offset |
+                                             IO_MEM_ROM);
+#endif
+    return size;
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
                      const char *boot_device, DisplayState *ds,
@@ -726,7 +758,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     int ret, linux_boot, i;
     ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset;
     ram_addr_t above_4g_mem_size = 0;
-    int bios_size, isa_bios_size, vga_bios_size;
+    int bios_size, isa_bios_size, vga_bios_size, opt_rom_offset;
     PCIBus *pci_bus;
     int piix3_devfn = -1;
     CPUState *env;
@@ -869,40 +901,13 @@ static void pc_init1(ram_addr_t ram_size, int 
vga_ram_size,
                                         /* | IO_MEM_ROM */);
 #endif
 
+    opt_rom_offset = 0;
+    for (i = 0; i < nb_option_roms; i++)
+       opt_rom_offset += load_option_rom(option_rom[i], opt_rom_offset);
 
-    {
-        ram_addr_t option_rom_offset;
-        int size, offset;
-
-        offset = 0;
-        for (i = 0; i < nb_option_roms; i++) {
-            size = get_image_size(option_rom[i]);
-            if (size < 0) {
-                fprintf(stderr, "Could not load option rom '%s'\n",
-                        option_rom[i]);
-                exit(1);
-            }
-            if (size > (0x10000 - offset))
-                goto option_rom_error;
-            option_rom_offset = qemu_ram_alloc(size);
-            ret = load_image(option_rom[i], phys_ram_base + option_rom_offset);
-            if (ret != size) {
-            option_rom_error:
-                fprintf(stderr, "Too many option ROMS\n");
-                exit(1);
-            }
-            size = (size + 4095) & ~4095;
-            cpu_register_physical_memory(0xd0000 + offset,
-                                         size, option_rom_offset | IO_MEM_ROM);
-#ifdef USE_KVM
-            if (kvm_allowed)
-                kvm_cpu_register_physical_memory(0xd0000 + offset,
-                                             size, option_rom_offset |
-                                             IO_MEM_ROM);
-#endif
-
-            offset += size;
-        }
+    if (extboot_drive != -1) {
+       snprintf(buf, sizeof(buf), "%s/%s", bios_dir, EXTBOOT_FILENAME);
+       opt_rom_offset += load_option_rom(buf, opt_rom_offset);
     }
 
     /* map all the bios at the top of memory */
@@ -1117,6 +1122,18 @@ static void pc_init1(ram_addr_t ram_size, int 
vga_ram_size,
            unit_id++;
        }
     }
+
+    if (extboot_drive != -1) {
+       DriveInfo *info = &drives_table[extboot_drive];
+       int cyls, heads, secs;
+
+       if (info->type != IF_IDE) {
+           bdrv_guess_geometry(info->bdrv, &cyls, &heads, &secs);
+           bdrv_set_geometry_hint(info->bdrv, cyls, heads, secs);
+       }
+
+       extboot_init(info->bdrv, 1);
+    }
 }
 
 static void pc_init_pci(ram_addr_t ram_size, int vga_ram_size,
diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h
index 5d4c747..7d1832f 100644
--- a/qemu/hw/pc.h
+++ b/qemu/hw/pc.h
@@ -151,4 +151,8 @@ void virtio_net_poll(void);
 void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
                      BlockDriverState *bs);
 
+/* extboot.c */
+
+void extboot_init(BlockDriverState *bs, int cmd);
+
 #endif
diff --git a/qemu/sysemu.h b/qemu/sysemu.h
index b9f4b43..a72a4d6 100644
--- a/qemu/sysemu.h
+++ b/qemu/sysemu.h
@@ -148,6 +148,7 @@ typedef struct DriveInfo {
 
 int nb_drives;
 DriveInfo drives_table[MAX_DRIVES+1];
+int extboot_drive;
 
 extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
 extern int drive_get_max_bus(BlockInterfaceType type);
diff --git a/qemu/vl.c b/qemu/vl.c
index c47b294..39b2e24 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -177,6 +177,7 @@ IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
    to store the VM snapshots */
 DriveInfo drives_table[MAX_DRIVES+1];
 int nb_drives;
+int extboot_drive = -1;
 /* point to the block driver where the snapshots are managed */
 BlockDriverState *bs_snapshots;
 int vga_ram_size;
@@ -4930,7 +4931,7 @@ static int drive_init(const char *str, int snapshot, 
QEMUMachine *machine)
     int bdrv_flags;
     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
                        "secs", "trans", "media", "snapshot", "file",
-                       "cache", NULL };
+                       "cache", "boot", NULL };
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n",
@@ -5101,6 +5102,19 @@ static int drive_init(const char *str, int snapshot, 
QEMUMachine *machine)
         }
     }
 
+    if (get_param_value(buf, sizeof(buf), "boot", str)) {
+       if (!strcmp(buf, "on")) {
+           if (extboot_drive != -1) {
+               fprintf(stderr, "qemu: two bootable drives specified\n");
+               return -1;
+           }
+           extboot_drive = nb_drives;
+       } else if (strcmp(buf, "off")) {
+           fprintf(stderr, "qemu: '%s' invalid boot option\n", str);
+           return -1;
+       }
+    }
+
     get_param_value(file, sizeof(file), "file", str);
 
     /* compute bus and unit according index */
@@ -7895,8 +7909,8 @@ static void help(int exitcode)
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 
master)\n"
           "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n"
-           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]"
-           "       [,cache=on|off]\n"
+           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n"
+           "       [,cache=on|off][,boot=on|off]\n"
           "                use 'file' as a drive image\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-commits mailing list
kvm-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-commits

Reply via email to