diff --git a/Makefile.target b/Makefile.target
index 67bd4d7..2314812 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -188,6 +188,7 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
+obj-i386-y += extboot.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/isa.o ide/pci.o ide/macio.o
diff --git a/hw/extboot.c b/hw/extboot.c
new file mode 100644
index 0000000..b91d54f
--- /dev/null
+++ b/hw/extboot.c
@@ -0,0 +1,135 @@
+/*
+ * 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 uint32_t extboot_read(void *opaque, uint32_t addr)
+{
+    int *pcmd = opaque;
+    return *pcmd;
+}
+
+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, int cmd)
+{
+    int *pcmd;
+
+    pcmd = qemu_mallocz(sizeof(int));
+
+    *pcmd = cmd;
+    register_ioport_read(0x404, 1, 1, extboot_read, pcmd);
+    register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);
+}
diff --git a/hw/pc.c b/hw/pc.c
index 6292001..a17dbd0 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -47,6 +47,7 @@
 #define BIOS_FILENAME "bios.bin"
 #define VGABIOS_FILENAME "vgabios.bin"
 #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
+#define EXTBOOT_FILENAME "extboot.bin"
 
 #define PC_MAX_BIOS_SIZE (4 * 1024 * 1024)
 
@@ -1130,7 +1131,7 @@ static void pc_init1(ram_addr_t ram_size,
     qemu_irq *isa_irq;
     qemu_irq *i8259;
     IsaIrqState *isa_irq_state;
-    DriveInfo *dinfo;
+    DriveInfo *dinfo, *boot_drive;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
@@ -1218,7 +1219,10 @@ static void pc_init1(ram_addr_t ram_size,
                                  isa_bios_size,
                                  (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 
-
+    boot_drive = drive_get_boot();
+    if (boot_drive) {
+        option_rom[nb_option_roms++] = qemu_strdup(EXTBOOT_FILENAME);
+    }
 
     option_rom_offset = qemu_ram_alloc(0x20000);
     oprom_area_size = 0;
@@ -1428,6 +1432,13 @@ static void pc_init1(ram_addr_t ram_size,
             }
         }
     }
+
+    if (boot_drive) {
+        int cyls, heads, secs;
+        bdrv_guess_geometry(boot_drive->bdrv, &cyls, &heads, &secs);
+        bdrv_set_geometry_hint(boot_drive->bdrv, cyls, heads, secs);
+        extboot_init(boot_drive->bdrv, 1);
+    }
 }
 
 static void pc_init_pci(ram_addr_t ram_size,
diff --git a/hw/pc.h b/hw/pc.h
index ec5735b..bd3c20a 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -151,4 +151,8 @@ void isa_cirrus_vga_init(void);
 void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
 
 int cpu_is_bsp(CPUState *env);
+
+/* extboot.c */
+void extboot_init(BlockDriverState *bs, int cmd);
+
 #endif
diff --git a/qemu-config.c b/qemu-config.c
index 4808db0..efea7f4 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -70,6 +70,10 @@ QemuOptsList qemu_drive_opts = {
             .name = "addr",
             .type = QEMU_OPT_STRING,
             .help = "pci address (virtio only)",
+        },{
+            .name = "boot",
+            .type = QEMU_OPT_BOOL,
+            .help = "make this a boot drive",
         },
         { /* end if list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index ce38a3b..df751ca 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -103,7 +103,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive,
     "-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]\n"
     "       [,cache=writethrough|writeback|none][,format=f][,serial=s]\n"
-    "       [,addr=A][,id=name][,aio=threads|native]\n"
+    "       [,addr=A][,id=name][,aio=threads|native][,boot=on]\n"
     "                use 'file' as a drive image\n")
 DEF("set", HAS_ARG, QEMU_OPTION_set,
     "-set group.id.arg=value\n"
diff --git a/sysemu.h b/sysemu.h
index ac16c21..dd24444 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -186,6 +186,7 @@ extern TAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
 
 extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 extern DriveInfo *drive_get_by_id(const char *id);
+extern DriveInfo *drive_get_boot(void);
 extern int drive_get_max_bus(BlockInterfaceType type);
 extern void drive_uninit(BlockDriverState *bdrv);
 extern const char *drive_get_serial(BlockDriverState *bdrv);
diff --git a/vl.c b/vl.c
index 098daaa..982b418 100644
--- a/vl.c
+++ b/vl.c
@@ -1843,6 +1843,18 @@ DriveInfo *drive_get_by_id(const char *id)
     return NULL;
 }
 
+DriveInfo *drive_get_boot(void)
+{
+    DriveInfo *dinfo;
+
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (qemu_opt_get_bool(dinfo->opts, "boot", 0) == 0)
+            continue;
+        return dinfo;
+    }
+    return NULL;
+}
+
 int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
