summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs7
-rw-r--r--Makefile.target7
-rw-r--r--audio/noaudio.c2
-rw-r--r--block.c2
-rw-r--r--block/rbd.c1059
-rw-r--r--block/rbd_types.h71
-rw-r--r--block_int.h5
-rwxr-xr-xconfigure52
-rw-r--r--cpu-common.h8
-rw-r--r--cpus.c2
-rw-r--r--exec.c142
-rw-r--r--hw/apb_pci.c9
-rw-r--r--hw/apic.c3
-rw-r--r--hw/arm_gic.c3
-rw-r--r--hw/arm_sysctl.c3
-rw-r--r--hw/arm_timer.c5
-rw-r--r--hw/armv7m.c2
-rw-r--r--hw/axis_dev88.c6
-rw-r--r--hw/bonito.c19
-rw-r--r--hw/cirrus_vga.c12
-rw-r--r--hw/cs4231.c3
-rw-r--r--hw/cs4231a.c1
-rw-r--r--hw/cuda.c3
-rw-r--r--hw/dec_pci.c6
-rw-r--r--hw/dp8393x.c3
-rw-r--r--hw/ds1225y.c6
-rw-r--r--hw/e1000.c15
-rw-r--r--hw/eccmemctl.c6
-rw-r--r--hw/eepro100.c6
-rw-r--r--hw/empty_slot.c3
-rw-r--r--hw/escc.c3
-rw-r--r--hw/esp.c3
-rw-r--r--hw/etraxfs_dma.c2
-rw-r--r--hw/etraxfs_eth.c3
-rw-r--r--hw/etraxfs_pic.c3
-rw-r--r--hw/etraxfs_ser.c3
-rw-r--r--hw/etraxfs_timer.c3
-rw-r--r--hw/fdc.c18
-rw-r--r--hw/file-op-9p.h2
-rw-r--r--hw/fw_cfg.c36
-rw-r--r--hw/fw_cfg.h4
-rw-r--r--hw/g364fb.c3
-rw-r--r--hw/grackle_pci.c6
-rw-r--r--hw/gt64xxx.c9
-rw-r--r--hw/gus.c4
-rw-r--r--hw/heathrow_pic.c5
-rw-r--r--hw/hpet.c3
-rw-r--r--hw/ide/cmd646.c4
-rw-r--r--hw/ide/internal.h3
-rw-r--r--hw/ide/isa.c5
-rw-r--r--hw/ide/macio.c3
-rw-r--r--hw/ide/mmio.c6
-rw-r--r--hw/ide/piix.c4
-rw-r--r--hw/ide/qdev.c22
-rw-r--r--hw/ide/via.c4
-rw-r--r--hw/integratorcp.c9
-rw-r--r--hw/intel-hda.c3
-rw-r--r--hw/ioapic.c3
-rw-r--r--hw/isa-bus.c53
-rw-r--r--hw/isa.h6
-rw-r--r--hw/isa_mmio.c100
-rw-r--r--hw/ivshmem.c2
-rw-r--r--hw/jazz_led.c3
-rw-r--r--hw/lan9118.c3
-rw-r--r--hw/lance.c4
-rw-r--r--hw/loader.c32
-rw-r--r--hw/loader.h8
-rw-r--r--hw/lsi53c895a.c6
-rw-r--r--hw/m48t59.c4
-rw-r--r--hw/mac_dbdma.c6
-rw-r--r--hw/mac_nvram.c3
-rw-r--r--hw/marvell_88w8618_audio.c3
-rw-r--r--hw/mc146818rtc.c1
-rw-r--r--hw/mcf5206.c3
-rw-r--r--hw/mcf5208.c6
-rw-r--r--hw/mcf_fec.c3
-rw-r--r--hw/mcf_intc.c3
-rw-r--r--hw/mcf_uart.c3
-rw-r--r--hw/mips_jazz.c13
-rw-r--r--hw/mips_malta.c3
-rw-r--r--hw/mips_mipssim.c6
-rw-r--r--hw/mips_r4k.c9
-rw-r--r--hw/mpcore.c3
-rw-r--r--hw/msix.c3
-rw-r--r--hw/mst_fpga.c2
-rw-r--r--hw/multiboot.c3
-rw-r--r--hw/musicpal.c24
-rw-r--r--hw/ne2000-isa.c3
-rw-r--r--hw/ne2000.c5
-rw-r--r--hw/nseries.c4
-rw-r--r--hw/omap.h3
-rw-r--r--hw/omap1.c42
-rw-r--r--hw/omap2.c4
-rw-r--r--hw/omap_dma.c4
-rw-r--r--hw/omap_dss.c2
-rw-r--r--hw/omap_gpio.c2
-rw-r--r--hw/omap_gpmc.c2
-rw-r--r--hw/omap_i2c.c2
-rw-r--r--hw/omap_intc.c4
-rw-r--r--hw/omap_l4.c5
-rw-r--r--hw/omap_lcdc.c2
-rw-r--r--hw/omap_mmc.c2
-rw-r--r--hw/omap_sdrc.c2
-rw-r--r--hw/omap_sx1.c15
-rw-r--r--hw/omap_uart.c2
-rw-r--r--hw/onenand.c2
-rw-r--r--hw/openpic.c29
-rw-r--r--hw/palm.c18
-rw-r--r--hw/parallel.c8
-rw-r--r--hw/pc.c7
-rw-r--r--hw/pc_piix.c20
-rw-r--r--hw/pci.c134
-rw-r--r--hw/pci.h7
-rw-r--r--hw/pci_host.c103
-rw-r--r--hw/pci_host.h6
-rw-r--r--hw/pcie.c8
-rw-r--r--hw/pcie_aer.c111
-rw-r--r--hw/pcie_host.c3
-rw-r--r--hw/pckbd.c6
-rw-r--r--hw/pcnet-pci.c5
-rw-r--r--hw/pcnet.c4
-rw-r--r--hw/pflash_cfi01.c6
-rw-r--r--hw/pflash_cfi02.c4
-rw-r--r--hw/piix_pci.c1
-rw-r--r--hw/pl011.c3
-rw-r--r--hw/pl022.c3
-rw-r--r--hw/pl031.c3
-rw-r--r--hw/pl050.c3
-rw-r--r--hw/pl061.c3
-rw-r--r--hw/pl080.c3
-rw-r--r--hw/pl110.c3
-rw-r--r--hw/pl181.c4
-rw-r--r--hw/pl190.c3
-rw-r--r--hw/ppc405_boards.c6
-rw-r--r--hw/ppc405_uc.c11
-rw-r--r--hw/ppc440.c2
-rw-r--r--hw/ppc4xx_pci.c19
-rw-r--r--hw/ppc_newworld.c5
-rw-r--r--hw/ppc_oldworld.c2
-rw-r--r--hw/ppc_prep.c40
-rw-r--r--hw/ppce500_mpc8544ds.c2
-rw-r--r--hw/ppce500_pci.c9
-rw-r--r--hw/prep_pci.c3
-rw-r--r--hw/pxa2xx.c25
-rw-r--r--hw/pxa2xx_dma.c2
-rw-r--r--hw/pxa2xx_gpio.c2
-rw-r--r--hw/pxa2xx_keypad.c2
-rw-r--r--hw/pxa2xx_lcd.c2
-rw-r--r--hw/pxa2xx_mmci.c2
-rw-r--r--hw/pxa2xx_pcmcia.c6
-rw-r--r--hw/pxa2xx_pic.c2
-rw-r--r--hw/pxa2xx_timer.c2
-rw-r--r--hw/qdev.c32
-rw-r--r--hw/qdev.h14
-rw-r--r--hw/r2d.c3
-rw-r--r--hw/rc4030.c6
-rw-r--r--hw/realview.c3
-rw-r--r--hw/realview_gic.c3
-rw-r--r--hw/rtl8139.c19
-rw-r--r--hw/sb16.c4
-rw-r--r--hw/sbi.c3
-rw-r--r--hw/scsi-bus.c23
-rw-r--r--hw/scsi-disk.c2
-rw-r--r--hw/serial.c7
-rw-r--r--hw/sh7750.c6
-rw-r--r--hw/sh_intc.c3
-rw-r--r--hw/sh_pci.c7
-rw-r--r--hw/sh_serial.c3
-rw-r--r--hw/sh_timer.c3
-rw-r--r--hw/slavio_intctl.c6
-rw-r--r--hw/slavio_misc.c24
-rw-r--r--hw/slavio_timer.c3
-rw-r--r--hw/sm501.c9
-rw-r--r--hw/smc91c111.c3
-rw-r--r--hw/sparc32_dma.c3
-rw-r--r--hw/spitz.c2
-rw-r--r--hw/stellaris.c12
-rw-r--r--hw/stellaris_enet.c3
-rw-r--r--hw/sun4c_intctl.c3
-rw-r--r--hw/sun4m_iommu.c3
-rw-r--r--hw/sun4u.c4
-rw-r--r--hw/syborg_fb.c3
-rw-r--r--hw/syborg_interrupt.c3
-rw-r--r--hw/syborg_keyboard.c3
-rw-r--r--hw/syborg_pointer.c3
-rw-r--r--hw/syborg_rtc.c3
-rw-r--r--hw/syborg_serial.c3
-rw-r--r--hw/syborg_timer.c3
-rw-r--r--hw/syborg_virtio.c3
-rw-r--r--hw/sysbus.c30
-rw-r--r--hw/sysbus.h4
-rw-r--r--hw/tc6393xb.c2
-rw-r--r--hw/tcx.c5
-rw-r--r--hw/tusb6010.c2
-rw-r--r--hw/unin_pci.c26
-rw-r--r--hw/usb-bus.c45
-rw-r--r--hw/usb-hub.c3
-rw-r--r--hw/usb-musb.c2
-rw-r--r--hw/usb-net.c3
-rw-r--r--hw/usb-ohci.c12
-rw-r--r--hw/usb-uhci.c2
-rw-r--r--hw/usb.h3
-rw-r--r--hw/versatile_pci.c21
-rw-r--r--hw/versatilepb.c3
-rw-r--r--hw/vga-isa-mm.c6
-rw-r--r--hw/vga.c3
-rw-r--r--hw/virtio-9p-debug.c4
-rw-r--r--hw/virtio-9p-local.c12
-rw-r--r--hw/virtio-9p-xattr.c3
-rw-r--r--hw/virtio-9p.c11
-rw-r--r--hw/virtio-blk.c2
-rw-r--r--hw/virtio-net.c71
-rw-r--r--hw/virtio-pci.c1
-rw-r--r--hw/vmware_vga.c2
-rw-r--r--hw/wdt_i6300esb.c43
-rw-r--r--hw/wdt_ib700.c20
-rw-r--r--hw/xilinx_ethlite.c2
-rw-r--r--hw/xilinx_intc.c2
-rw-r--r--hw/xilinx_timer.c3
-rw-r--r--hw/xilinx_uartlite.c3
-rw-r--r--hw/zaurus.c2
-rw-r--r--migration.c2
-rw-r--r--monitor.c413
-rw-r--r--net.c4
-rw-r--r--net.h4
-rw-r--r--net/socket.c52
-rw-r--r--oslib-posix.c48
-rw-r--r--qemu-config.c17
-rw-r--r--qemu-img.c247
-rw-r--r--qemu-malloc.c5
-rw-r--r--qemu-option.c13
-rw-r--r--qemu-options.hx11
-rw-r--r--qemu-os-posix.h12
-rw-r--r--qmp-commands.hx2
-rw-r--r--rwhandler.c4
-rw-r--r--rwhandler.h2
-rw-r--r--savevm.c4
-rw-r--r--sysemu.h11
-rw-r--r--target-ppc/kvm.c2
-rw-r--r--vl.c114
240 files changed, 3263 insertions, 1021 deletions
diff --git a/Makefile.objs b/Makefile.objs
index 04625eb10f..24b2f99a43 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -24,6 +24,7 @@ block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
 block-nested-$(CONFIG_WIN32) += raw-win32.o
 block-nested-$(CONFIG_POSIX) += raw-posix.o
 block-nested-$(CONFIG_CURL) += curl.o
+block-nested-$(CONFIG_RBD) += rbd.o
 
 block-obj-y +=  $(addprefix block/, $(block-nested-y))
 
@@ -168,7 +169,8 @@ hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
 hw-obj-y += fw_cfg.o
 # FIXME: Core PCI code and its direct dependencies are required by the
 # QMP query-pci command.
-hw-obj-y += pci.o pci_bridge.o msix.o msi.o
+hw-obj-y += pci.o pci_bridge.o
+hw-obj-$(CONFIG_PCI) += msix.o msi.o
 hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
 hw-obj-y += watchdog.o
@@ -188,6 +190,7 @@ hw-obj-$(CONFIG_I8254) += i8254.o
 hw-obj-$(CONFIG_PCSPK) += pcspk.o
 hw-obj-$(CONFIG_PCKBD) += pckbd.o
 hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
+hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
 hw-obj-$(CONFIG_FDC) += fdc.o
 hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
 hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
@@ -224,6 +227,8 @@ hw-obj-$(CONFIG_NE2000_PCI) += ne2000.o
 hw-obj-$(CONFIG_EEPRO100_PCI) += eepro100.o
 hw-obj-$(CONFIG_PCNET_PCI) += pcnet-pci.o
 hw-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
+hw-obj-$(CONFIG_E1000_PCI) += e1000.o
+hw-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
 
 hw-obj-$(CONFIG_SMC91C111) += smc91c111.o
 hw-obj-$(CONFIG_LAN9118) += lan9118.o
diff --git a/Makefile.target b/Makefile.target
index 578484452b..d08f5dd4ef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -206,13 +206,6 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 # xen backend driver support
 obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
 
-# USB layer
-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
-
-# PCI network cards
-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
-obj-$(CONFIG_E1000_PCI) += e1000.o
-
 # Inter-VM PCI shared memory
 obj-$(CONFIG_KVM) += ivshmem.o
 
diff --git a/audio/noaudio.c b/audio/noaudio.c
index 4925234c07..80158583b2 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -121,7 +121,7 @@ static int no_read (SWVoiceIn *sw, void *buf, int size)
     int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
     int to_clear = audio_MIN (samples, total);
     audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
-    return to_clear;
+    return to_clear << sw->info.shift;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
diff --git a/block.c b/block.c
index 63effd8769..e7a986c48a 100644
--- a/block.c
+++ b/block.c
@@ -215,7 +215,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
 
     drv = bdrv_find_protocol(filename);
     if (drv == NULL) {
-        drv = bdrv_find_format("file");
+        return -ENOENT;
     }
 
     return bdrv_create(drv, filename, options);
diff --git a/block/rbd.c b/block/rbd.c
new file mode 100644
index 0000000000..249a590c98
--- /dev/null
+++ b/block/rbd.c
@@ -0,0 +1,1059 @@
+/*
+ * QEMU Block driver for RADOS (Ceph)
+ *
+ * Copyright (C) 2010 Christian Brunner <chb@muc.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu-error.h"
+
+#include "rbd_types.h"
+#include "block_int.h"
+
+#include <rados/librados.h>
+
+
+
+/*
+ * When specifying the image filename use:
+ *
+ * rbd:poolname/devicename
+ *
+ * poolname must be the name of an existing rados pool
+ *
+ * devicename is the basename for all objects used to
+ * emulate the raw device.
+ *
+ * Metadata information (image size, ...) is stored in an
+ * object with the name "devicename.rbd".
+ *
+ * The raw device is split into 4MB sized objects by default.
+ * The sequencenumber is encoded in a 12 byte long hex-string,
+ * and is attached to the devicename, separated by a dot.
+ * e.g. "devicename.1234567890ab"
+ *
+ */
+
+#define OBJ_MAX_SIZE (1UL << OBJ_DEFAULT_OBJ_ORDER)
+
+typedef struct RBDAIOCB {
+    BlockDriverAIOCB common;
+    QEMUBH *bh;
+    int ret;
+    QEMUIOVector *qiov;
+    char *bounce;
+    int write;
+    int64_t sector_num;
+    int aiocnt;
+    int error;
+    struct BDRVRBDState *s;
+    int cancelled;
+} RBDAIOCB;
+
+typedef struct RADOSCB {
+    int rcbid;
+    RBDAIOCB *acb;
+    struct BDRVRBDState *s;
+    int done;
+    int64_t segsize;
+    char *buf;
+    int ret;
+} RADOSCB;
+
+#define RBD_FD_READ 0
+#define RBD_FD_WRITE 1
+
+typedef struct BDRVRBDState {
+    int fds[2];
+    rados_pool_t pool;
+    rados_pool_t header_pool;
+    char name[RBD_MAX_OBJ_NAME_SIZE];
+    char block_name[RBD_MAX_BLOCK_NAME_SIZE];
+    uint64_t size;
+    uint64_t objsize;
+    int qemu_aio_count;
+    int event_reader_pos;
+    RADOSCB *event_rcb;
+} BDRVRBDState;
+
+typedef struct rbd_obj_header_ondisk RbdHeader1;
+
+static void rbd_aio_bh_cb(void *opaque);
+
+static int rbd_next_tok(char *dst, int dst_len,
+                        char *src, char delim,
+                        const char *name,
+                        char **p)
+{
+    int l;
+    char *end;
+
+    *p = NULL;
+
+    if (delim != '\0') {
+        end = strchr(src, delim);
+        if (end) {
+            *p = end + 1;
+            *end = '\0';
+        }
+    }
+    l = strlen(src);
+    if (l >= dst_len) {
+        error_report("%s too long", name);
+        return -EINVAL;
+    } else if (l == 0) {
+        error_report("%s too short", name);
+        return -EINVAL;
+    }
+
+    pstrcpy(dst, dst_len, src);
+
+    return 0;
+}
+
+static int rbd_parsename(const char *filename,
+                         char *pool, int pool_len,
+                         char *snap, int snap_len,
+                         char *name, int name_len)
+{
+    const char *start;
+    char *p, *buf;
+    int ret;
+
+    if (!strstart(filename, "rbd:", &start)) {
+        return -EINVAL;
+    }
+
+    buf = qemu_strdup(start);
+    p = buf;
+
+    ret = rbd_next_tok(pool, pool_len, p, '/', "pool name", &p);
+    if (ret < 0 || !p) {
+        ret = -EINVAL;
+        goto done;
+    }
+    ret = rbd_next_tok(name, name_len, p, '@', "object name", &p);
+    if (ret < 0) {
+        goto done;
+    }
+    if (!p) {
+        *snap = '\0';
+        goto done;
+    }
+
+    ret = rbd_next_tok(snap, snap_len, p, '\0', "snap name", &p);
+
+done:
+    qemu_free(buf);
+    return ret;
+}
+
+static int create_tmap_op(uint8_t op, const char *name, char **tmap_desc)
+{
+    uint32_t len = strlen(name);
+    uint32_t len_le = cpu_to_le32(len);
+    /* total_len = encoding op + name + empty buffer */
+    uint32_t total_len = 1 + (sizeof(uint32_t) + len) + sizeof(uint32_t);
+    uint8_t *desc = NULL;
+
+    desc = qemu_malloc(total_len);
+
+    *tmap_desc = (char *)desc;
+
+    *desc = op;
+    desc++;
+    memcpy(desc, &len_le, sizeof(len_le));
+    desc += sizeof(len_le);
+    memcpy(desc, name, len);
+    desc += len;
+    len = 0; /* no need for endian conversion for 0 */
+    memcpy(desc, &len, sizeof(len));
+    desc += sizeof(len);
+
+    return (char *)desc - *tmap_desc;
+}
+
+static void free_tmap_op(char *tmap_desc)
+{
+    qemu_free(tmap_desc);
+}
+
+static int rbd_register_image(rados_pool_t pool, const char *name)
+{
+    char *tmap_desc;
+    const char *dir = RBD_DIRECTORY;
+    int ret;
+
+    ret = create_tmap_op(CEPH_OSD_TMAP_SET, name, &tmap_desc);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = rados_tmap_update(pool, dir, tmap_desc, ret);
+    free_tmap_op(tmap_desc);
+
+    return ret;
+}
+
+static int touch_rbd_info(rados_pool_t pool, const char *info_oid)
+{
+    int r = rados_write(pool, info_oid, 0, NULL, 0);
+    if (r < 0) {
+        return r;
+    }
+    return 0;
+}
+
+static int rbd_assign_bid(rados_pool_t pool, uint64_t *id)
+{
+    uint64_t out[1];
+    const char *info_oid = RBD_INFO;
+
+    *id = 0;
+
+    int r = touch_rbd_info(pool, info_oid);
+    if (r < 0) {
+        return r;
+    }
+
+    r = rados_exec(pool, info_oid, "rbd", "assign_bid", NULL,
+                   0, (char *)out, sizeof(out));
+    if (r < 0) {
+        return r;
+    }
+
+    le64_to_cpus(out);
+    *id = out[0];
+
+    return 0;
+}
+
+static int rbd_create(const char *filename, QEMUOptionParameter *options)
+{
+    int64_t bytes = 0;
+    int64_t objsize;
+    uint64_t size;
+    time_t mtime;
+    uint8_t obj_order = RBD_DEFAULT_OBJ_ORDER;
+    char pool[RBD_MAX_SEG_NAME_SIZE];
+    char n[RBD_MAX_SEG_NAME_SIZE];
+    char name[RBD_MAX_OBJ_NAME_SIZE];
+    char snap_buf[RBD_MAX_SEG_NAME_SIZE];
+    char *snap = NULL;
+    RbdHeader1 header;
+    rados_pool_t p;
+    uint64_t bid;
+    uint32_t hi, lo;
+    int ret;
+
+    if (rbd_parsename(filename,
+                      pool, sizeof(pool),
+                      snap_buf, sizeof(snap_buf),
+                      name, sizeof(name)) < 0) {
+        return -EINVAL;
+    }
+    if (snap_buf[0] != '\0') {
+        snap = snap_buf;
+    }
+
+    snprintf(n, sizeof(n), "%s%s", name, RBD_SUFFIX);
+
+    /* Read out options */
+    while (options && options->name) {
+        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+            bytes = options->value.n;
+        } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) {
+            if (options->value.n) {
+                objsize = options->value.n;
+                if ((objsize - 1) & objsize) {    /* not a power of 2? */
+                    error_report("obj size needs to be power of 2");
+                    return -EINVAL;
+                }
+                if (objsize < 4096) {
+                    error_report("obj size too small");
+                    return -EINVAL;
+                }
+		obj_order = ffs(objsize) - 1;
+            }
+        }
+        options++;
+    }
+
+    memset(&header, 0, sizeof(header));
+    pstrcpy(header.text, sizeof(header.text), RBD_HEADER_TEXT);
+    pstrcpy(header.signature, sizeof(header.signature), RBD_HEADER_SIGNATURE);
+    pstrcpy(header.version, sizeof(header.version), RBD_HEADER_VERSION);
+    header.image_size = cpu_to_le64(bytes);
+    header.options.order = obj_order;
+    header.options.crypt_type = RBD_CRYPT_NONE;
+    header.options.comp_type = RBD_COMP_NONE;
+    header.snap_seq = 0;
+    header.snap_count = 0;
+
+    if (rados_initialize(0, NULL) < 0) {
+        error_report("error initializing");
+        return -EIO;
+    }
+
+    if (rados_open_pool(pool, &p)) {
+        error_report("error opening pool %s", pool);
+        rados_deinitialize();
+        return -EIO;
+    }
+
+    /* check for existing rbd header file */
+    ret = rados_stat(p, n, &size, &mtime);
+    if (ret == 0) {
+        ret=-EEXIST;
+        goto done;
+    }
+
+    ret = rbd_assign_bid(p, &bid);
+    if (ret < 0) {
+        error_report("failed assigning block id");
+        rados_deinitialize();
+        return -EIO;
+    }
+    hi = bid >> 32;
+    lo = bid & 0xFFFFFFFF;
+    snprintf(header.block_name, sizeof(header.block_name), "rb.%x.%x", hi, lo);
+
+    /* create header file */
+    ret = rados_write(p, n, 0, (const char *)&header, sizeof(header));
+    if (ret < 0) {
+        goto done;
+    }
+
+    ret = rbd_register_image(p, name);
+done:
+    rados_close_pool(p);
+    rados_deinitialize();
+
+    return ret;
+}
+
+/*
+ * This aio completion is being called from rbd_aio_event_reader() and
+ * runs in qemu context. It schedules a bh, but just in case the aio
+ * was not cancelled before.
+ */
+static void rbd_complete_aio(RADOSCB *rcb)
+{
+    RBDAIOCB *acb = rcb->acb;
+    int64_t r;
+
+    acb->aiocnt--;
+
+    if (acb->cancelled) {
+        if (!acb->aiocnt) {
+            qemu_vfree(acb->bounce);
+            qemu_aio_release(acb);
+        }
+        goto done;
+    }
+
+    r = rcb->ret;
+
+    if (acb->write) {
+        if (r < 0) {
+            acb->ret = r;
+            acb->error = 1;
+        } else if (!acb->error) {
+            acb->ret += rcb->segsize;
+        }
+    } else {
+        if (r == -ENOENT) {
+            memset(rcb->buf, 0, rcb->segsize);
+            if (!acb->error) {
+                acb->ret += rcb->segsize;
+            }
+        } else if (r < 0) {
+	    memset(rcb->buf, 0, rcb->segsize);
+            acb->ret = r;
+            acb->error = 1;
+        } else if (r < rcb->segsize) {
+            memset(rcb->buf + r, 0, rcb->segsize - r);
+            if (!acb->error) {
+                acb->ret += rcb->segsize;
+            }
+        } else if (!acb->error) {
+            acb->ret += r;
+        }
+    }
+    /* Note that acb->bh can be NULL in case where the aio was cancelled */
+    if (!acb->aiocnt) {
+        acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb);
+        qemu_bh_schedule(acb->bh);
+    }
+done:
+    qemu_free(rcb);
+}
+
+/*
+ * aio fd read handler. It runs in the qemu context and calls the
+ * completion handling of completed rados aio operations.
+ */
+static void rbd_aio_event_reader(void *opaque)
+{
+    BDRVRBDState *s = opaque;
+
+    ssize_t ret;
+
+    do {
+        char *p = (char *)&s->event_rcb;
+
+        /* now read the rcb pointer that was sent from a non qemu thread */
+        if ((ret = read(s->fds[RBD_FD_READ], p + s->event_reader_pos,
+                        sizeof(s->event_rcb) - s->event_reader_pos)) > 0) {
+            if (ret > 0) {
+                s->event_reader_pos += ret;
+                if (s->event_reader_pos == sizeof(s->event_rcb)) {
+                    s->event_reader_pos = 0;
+                    rbd_complete_aio(s->event_rcb);
+                    s->qemu_aio_count --;
+                }
+            }
+        }
+    } while (ret < 0 && errno == EINTR);
+}
+
+static int rbd_aio_flush_cb(void *opaque)
+{
+    BDRVRBDState *s = opaque;
+
+    return (s->qemu_aio_count > 0);
+}
+
+
+static int rbd_set_snapc(rados_pool_t pool, const char *snap, RbdHeader1 *header)
+{
+    uint32_t snap_count = le32_to_cpu(header->snap_count);
+    rados_snap_t *snaps = NULL;
+    rados_snap_t seq;
+    uint32_t i;
+    uint64_t snap_names_len = le64_to_cpu(header->snap_names_len);
+    int r;
+    rados_snap_t snapid = 0;
+
+    if (snap_count) {
+        const char *header_snap = (const char *)&header->snaps[snap_count];
+        const char *end = header_snap + snap_names_len;
+        snaps = qemu_malloc(sizeof(rados_snap_t) * header->snap_count);
+
+        for (i=0; i < snap_count; i++) {
+            snaps[i] = le64_to_cpu(header->snaps[i].id);
+
+            if (snap && strcmp(snap, header_snap) == 0) {
+                snapid = snaps[i];
+            }
+
+            header_snap += strlen(header_snap) + 1;
+            if (header_snap > end) {
+                error_report("bad header, snapshot list broken");
+            }
+        }
+    }
+
+    if (snap && !snapid) {
+        error_report("snapshot not found");
+        qemu_free(snaps);
+        return -ENOENT;
+    }
+    seq = le32_to_cpu(header->snap_seq);
+
+    r = rados_set_snap_context(pool, seq, snaps, snap_count);
+
+    rados_set_snap(pool, snapid);
+
+    qemu_free(snaps);
+
+    return r;
+}
+
+#define BUF_READ_START_LEN    4096
+
+static int rbd_read_header(BDRVRBDState *s, char **hbuf)
+{
+    char *buf = NULL;
+    char n[RBD_MAX_SEG_NAME_SIZE];
+    uint64_t len = BUF_READ_START_LEN;
+    int r;
+
+    snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX);
+
+    buf = qemu_malloc(len);
+
+    r = rados_read(s->header_pool, n, 0, buf, len);
+    if (r < 0) {
+        goto failed;
+    }
+
+    if (r < len) {
+        goto done;
+    }
+
+    qemu_free(buf);
+    buf = qemu_malloc(len);
+
+    r = rados_stat(s->header_pool, n, &len, NULL);
+    if (r < 0) {
+        goto failed;
+    }
+
+    r = rados_read(s->header_pool, n, 0, buf, len);
+    if (r < 0) {
+        goto failed;
+    }
+
+done:
+    *hbuf = buf;
+    return 0;
+
+failed:
+    qemu_free(buf);
+    return r;
+}
+
+static int rbd_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    BDRVRBDState *s = bs->opaque;
+    RbdHeader1 *header;
+    char pool[RBD_MAX_SEG_NAME_SIZE];
+    char snap_buf[RBD_MAX_SEG_NAME_SIZE];
+    char *snap = NULL;
+    char *hbuf = NULL;
+    int r;
+
+    if (rbd_parsename(filename, pool, sizeof(pool),
+                      snap_buf, sizeof(snap_buf),
+                      s->name, sizeof(s->name)) < 0) {
+        return -EINVAL;
+    }
+    if (snap_buf[0] != '\0') {
+        snap = snap_buf;
+    }
+
+    if ((r = rados_initialize(0, NULL)) < 0) {
+        error_report("error initializing");
+        return r;
+    }
+
+    if ((r = rados_open_pool(pool, &s->pool))) {
+        error_report("error opening pool %s", pool);
+        rados_deinitialize();
+        return r;
+    }
+
+    if ((r = rados_open_pool(pool, &s->header_pool))) {
+        error_report("error opening pool %s", pool);
+        rados_deinitialize();
+        return r;
+    }
+
+    if ((r = rbd_read_header(s, &hbuf)) < 0) {
+        error_report("error reading header from %s", s->name);
+        goto failed;
+    }
+
+    if (memcmp(hbuf + 64, RBD_HEADER_SIGNATURE, 4)) {
+        error_report("Invalid header signature");
+        r = -EMEDIUMTYPE;
+        goto failed;
+    }
+
+    if (memcmp(hbuf + 68, RBD_HEADER_VERSION, 8)) {
+        error_report("Unknown image version");
+        r = -EMEDIUMTYPE;
+        goto failed;
+    }
+
+    header = (RbdHeader1 *) hbuf;
+    s->size = le64_to_cpu(header->image_size);
+    s->objsize = 1ULL << header->options.order;
+    memcpy(s->block_name, header->block_name, sizeof(header->block_name));
+
+    r = rbd_set_snapc(s->pool, snap, header);
+    if (r < 0) {
+        error_report("failed setting snap context: %s", strerror(-r));
+        goto failed;
+    }
+
+    bs->read_only = (snap != NULL);
+
+    s->event_reader_pos = 0;
+    r = qemu_pipe(s->fds);
+    if (r < 0) {
+        error_report("error opening eventfd");
+        goto failed;
+    }
+    fcntl(s->fds[0], F_SETFL, O_NONBLOCK);
+    fcntl(s->fds[1], F_SETFL, O_NONBLOCK);
+    qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], rbd_aio_event_reader, NULL,
+        rbd_aio_flush_cb, NULL, s);
+
+    qemu_free(hbuf);
+
+    return 0;
+
+failed:
+    qemu_free(hbuf);
+
+    rados_close_pool(s->header_pool);
+    rados_close_pool(s->pool);
+    rados_deinitialize();
+    return r;
+}
+
+static void rbd_close(BlockDriverState *bs)
+{
+    BDRVRBDState *s = bs->opaque;
+
+    close(s->fds[0]);
+    close(s->fds[1]);
+    qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL , NULL, NULL, NULL,
+        NULL);
+
+    rados_close_pool(s->header_pool);
+    rados_close_pool(s->pool);
+    rados_deinitialize();
+}
+
+/*
+ * Cancel aio. Since we don't reference acb in a non qemu threads,
+ * it is safe to access it here.
+ */
+static void rbd_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+    RBDAIOCB *acb = (RBDAIOCB *) blockacb;
+    acb->cancelled = 1;
+}
+
+static AIOPool rbd_aio_pool = {
+    .aiocb_size = sizeof(RBDAIOCB),
+    .cancel = rbd_aio_cancel,
+};
+
+/*
+ * This is the callback function for rados_aio_read and _write
+ *
+ * Note: this function is being called from a non qemu thread so
+ * we need to be careful about what we do here. Generally we only
+ * write to the block notification pipe, and do the rest of the
+ * io completion handling from rbd_aio_event_reader() which
+ * runs in a qemu context.
+ */
+static void rbd_finish_aiocb(rados_completion_t c, RADOSCB *rcb)
+{
+    int ret;
+    rcb->ret = rados_aio_get_return_value(c);
+    rados_aio_release(c);
+    while (1) {
+        fd_set wfd;
+        int fd = rcb->s->fds[RBD_FD_WRITE];
+
+        /* send the rcb pointer to the qemu thread that is responsible
+           for the aio completion. Must do it in a qemu thread context */
+        ret = write(fd, (void *)&rcb, sizeof(rcb));
+        if (ret >= 0) {
+            break;
+        }
+        if (errno == EINTR) {
+            continue;
+	}
+        if (errno != EAGAIN) {
+            break;
+	}
+
+        FD_ZERO(&wfd);
+        FD_SET(fd, &wfd);
+        do {
+            ret = select(fd + 1, NULL, &wfd, NULL, NULL);
+        } while (ret < 0 && errno == EINTR);
+    }
+
+    if (ret < 0) {
+        error_report("failed writing to acb->s->fds\n");
+        qemu_free(rcb);
+    }
+}
+
+/* Callback when all queued rados_aio requests are complete */
+
+static void rbd_aio_bh_cb(void *opaque)
+{
+    RBDAIOCB *acb = opaque;
+
+    if (!acb->write) {
+        qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
+    }
+    qemu_vfree(acb->bounce);
+    acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
+    qemu_bh_delete(acb->bh);
+    acb->bh = NULL;
+
+    qemu_aio_release(acb);
+}
+
+static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs,
+                                           int64_t sector_num,
+                                           QEMUIOVector *qiov,
+                                           int nb_sectors,
+                                           BlockDriverCompletionFunc *cb,
+                                           void *opaque, int write)
+{
+    RBDAIOCB *acb;
+    RADOSCB *rcb;
+    rados_completion_t c;
+    char n[RBD_MAX_SEG_NAME_SIZE];
+    int64_t segnr, segoffs, segsize, last_segnr;
+    int64_t off, size;
+    char *buf;
+
+    BDRVRBDState *s = bs->opaque;
+
+    acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque);
+    acb->write = write;
+    acb->qiov = qiov;
+    acb->bounce = qemu_blockalign(bs, qiov->size);
+    acb->aiocnt = 0;
+    acb->ret = 0;
+    acb->error = 0;
+    acb->s = s;
+    acb->cancelled = 0;
+    acb->bh = NULL;
+
+    if (write) {
+        qemu_iovec_to_buffer(acb->qiov, acb->bounce);
+    }
+
+    buf = acb->bounce;
+
+    off = sector_num * BDRV_SECTOR_SIZE;
+    size = nb_sectors * BDRV_SECTOR_SIZE;
+    segnr = off / s->objsize;
+    segoffs = off % s->objsize;
+    segsize = s->objsize - segoffs;
+
+    last_segnr = ((off + size - 1) / s->objsize);
+    acb->aiocnt = (last_segnr - segnr) + 1;
+
+    s->qemu_aio_count += acb->aiocnt; /* All the RADOSCB */
+
+    while (size > 0) {
+        if (size < segsize) {
+            segsize = size;
+        }
+
+        snprintf(n, sizeof(n), "%s.%012" PRIx64, s->block_name,
+                 segnr);
+
+        rcb = qemu_malloc(sizeof(RADOSCB));
+        rcb->done = 0;
+        rcb->acb = acb;
+        rcb->segsize = segsize;
+        rcb->buf = buf;
+        rcb->s = acb->s;
+
+        if (write) {
+            rados_aio_create_completion(rcb, NULL,
+                                        (rados_callback_t) rbd_finish_aiocb,
+                                        &c);
+            rados_aio_write(s->pool, n, segoffs, buf, segsize, c);
+        } else {
+            rados_aio_create_completion(rcb,
+                                        (rados_callback_t) rbd_finish_aiocb,
+                                        NULL, &c);
+            rados_aio_read(s->pool, n, segoffs, buf, segsize, c);
+        }
+
+        buf += segsize;
+        size -= segsize;
+        segoffs = 0;
+        segsize = s->objsize;
+        segnr++;
+    }
+
+    return &acb->common;
+}
+
+static BlockDriverAIOCB *rbd_aio_readv(BlockDriverState * bs,
+                                       int64_t sector_num, QEMUIOVector * qiov,
+                                       int nb_sectors,
+                                       BlockDriverCompletionFunc * cb,
+                                       void *opaque)
+{
+    return rbd_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
+}
+
+static BlockDriverAIOCB *rbd_aio_writev(BlockDriverState * bs,
+                                        int64_t sector_num, QEMUIOVector * qiov,
+                                        int nb_sectors,
+                                        BlockDriverCompletionFunc * cb,
+                                        void *opaque)
+{
+    return rbd_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
+}
+
+static int rbd_getinfo(BlockDriverState * bs, BlockDriverInfo * bdi)
+{
+    BDRVRBDState *s = bs->opaque;
+    bdi->cluster_size = s->objsize;
+    return 0;
+}
+
+static int64_t rbd_getlength(BlockDriverState * bs)
+{
+    BDRVRBDState *s = bs->opaque;
+
+    return s->size;
+}
+
+static int rbd_snap_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
+{
+    BDRVRBDState *s = bs->opaque;
+    char inbuf[512], outbuf[128];
+    uint64_t snap_id;
+    int r;
+    char *p = inbuf;
+    char *end = inbuf + sizeof(inbuf);
+    char n[RBD_MAX_SEG_NAME_SIZE];
+    char *hbuf = NULL;
+    RbdHeader1 *header;
+
+    if (sn_info->name[0] == '\0') {
+        return -EINVAL; /* we need a name for rbd snapshots */
+    }
+
+    /*
+     * rbd snapshots are using the name as the user controlled unique identifier
+     * we can't use the rbd snapid for that purpose, as it can't be set
+     */
+    if (sn_info->id_str[0] != '\0' &&
+        strcmp(sn_info->id_str, sn_info->name) != 0) {
+        return -EINVAL;
+    }
+
+    if (strlen(sn_info->name) >= sizeof(sn_info->id_str)) {
+        return -ERANGE;
+    }
+
+    r = rados_selfmanaged_snap_create(s->header_pool, &snap_id);
+    if (r < 0) {
+        error_report("failed to create snap id: %s", strerror(-r));
+        return r;
+    }
+
+    *(uint32_t *)p = strlen(sn_info->name);
+    cpu_to_le32s((uint32_t *)p);
+    p += sizeof(uint32_t);
+    strncpy(p, sn_info->name, end - p);
+    p += strlen(p);
+    if (p + sizeof(snap_id) > end) {
+        error_report("invalid input parameter");
+        return -EINVAL;
+    }
+
+    *(uint64_t *)p = snap_id;
+    cpu_to_le64s((uint64_t *)p);
+
+    snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX);
+
+    r = rados_exec(s->header_pool, n, "rbd", "snap_add", inbuf,
+                   sizeof(inbuf), outbuf, sizeof(outbuf));
+    if (r < 0) {
+        error_report("rbd.snap_add execution failed failed: %s", strerror(-r));
+        return r;
+    }
+
+    sprintf(sn_info->id_str, "%s", sn_info->name);
+
+    r = rbd_read_header(s, &hbuf);
+    if (r < 0) {
+        error_report("failed reading header: %s", strerror(-r));
+        return r;
+    }
+
+    header = (RbdHeader1 *) hbuf;
+    r = rbd_set_snapc(s->pool, sn_info->name, header);
+    if (r < 0) {
+        error_report("failed setting snap context: %s", strerror(-r));
+        goto failed;
+    }
+
+    return 0;
+
+failed:
+    qemu_free(header);
+    return r;
+}
+
+static int decode32(char **p, const char *end, uint32_t *v)
+{
+    if (*p + 4 > end) {
+	return -ERANGE;
+    }
+
+    *v = *(uint32_t *)(*p);
+    le32_to_cpus(v);
+    *p += 4;
+    return 0;
+}
+
+static int decode64(char **p, const char *end, uint64_t *v)
+{
+    if (*p + 8 > end) {
+        return -ERANGE;
+    }
+
+    *v = *(uint64_t *)(*p);
+    le64_to_cpus(v);
+    *p += 8;
+    return 0;
+}
+
+static int decode_str(char **p, const char *end, char **s)
+{
+    uint32_t len;
+    int r;
+
+    if ((r = decode32(p, end, &len)) < 0) {
+        return r;
+    }
+
+    *s = qemu_malloc(len + 1);
+    memcpy(*s, *p, len);
+    *p += len;
+    (*s)[len] = '\0';
+
+    return len;
+}
+
+static int rbd_snap_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
+{
+    BDRVRBDState *s = bs->opaque;
+    char n[RBD_MAX_SEG_NAME_SIZE];
+    QEMUSnapshotInfo *sn_info, *sn_tab = NULL;
+    RbdHeader1 *header;
+    char *hbuf = NULL;
+    char *outbuf = NULL, *end, *buf;
+    uint64_t len;
+    uint64_t snap_seq;
+    uint32_t snap_count;
+    int r, i;
+
+    /* read header to estimate how much space we need to read the snap
+     * list */
+    if ((r = rbd_read_header(s, &hbuf)) < 0) {
+        goto done_err;
+    }
+    header = (RbdHeader1 *)hbuf;
+    len = le64_to_cpu(header->snap_names_len);
+    len += 1024; /* should have already been enough, but new snapshots might
+                    already been created since we read the header. just allocate
+                    a bit more, so that in most cases it'll suffice anyway */
+    qemu_free(hbuf);
+
+    snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX);
+    while (1) {
+        qemu_free(outbuf);
+        outbuf = qemu_malloc(len);
+
+        r = rados_exec(s->header_pool, n, "rbd", "snap_list", NULL, 0,
+                       outbuf, len);
+        if (r < 0) {
+            error_report("rbd.snap_list execution failed failed: %s", strerror(-r));
+            goto done_err;
+        }
+        if (r != len) {
+            break;
+	}
+
+        /* if we're here, we probably raced with some snaps creation */
+        len *= 2;
+    }
+    buf = outbuf;
+    end = buf + len;
+
+    if ((r = decode64(&buf, end, &snap_seq)) < 0) {
+        goto done_err;
+    }
+    if ((r = decode32(&buf, end, &snap_count)) < 0) {
+        goto done_err;
+    }
+
+    sn_tab = qemu_mallocz(snap_count * sizeof(QEMUSnapshotInfo));
+    for (i = 0; i < snap_count; i++) {
+        uint64_t id, image_size;
+        char *snap_name;
+
+        if ((r = decode64(&buf, end, &id)) < 0) {
+            goto done_err;
+        }
+        if ((r = decode64(&buf, end, &image_size)) < 0) {
+            goto done_err;
+        }
+        if ((r = decode_str(&buf, end, &snap_name)) < 0) {
+            goto done_err;
+        }
+
+        sn_info = sn_tab + i;
+        pstrcpy(sn_info->id_str, sizeof(sn_info->id_str), snap_name);
+        pstrcpy(sn_info->name, sizeof(sn_info->name), snap_name);
+        qemu_free(snap_name);
+
+        sn_info->vm_state_size = image_size;
+        sn_info->date_sec = 0;
+        sn_info->date_nsec = 0;
+        sn_info->vm_clock_nsec = 0;
+    }
+    *psn_tab = sn_tab;
+    qemu_free(outbuf);
+    return snap_count;
+done_err:
+    qemu_free(sn_tab);
+    qemu_free(outbuf);
+    return r;
+}
+
+static QEMUOptionParameter rbd_create_options[] = {
+    {
+     .name = BLOCK_OPT_SIZE,
+     .type = OPT_SIZE,
+     .help = "Virtual disk size"
+    },
+    {
+     .name = BLOCK_OPT_CLUSTER_SIZE,
+     .type = OPT_SIZE,
+     .help = "RBD object size"
+    },
+    {NULL}
+};
+
+static BlockDriver bdrv_rbd = {
+    .format_name        = "rbd",
+    .instance_size      = sizeof(BDRVRBDState),
+    .bdrv_file_open     = rbd_open,
+    .bdrv_close         = rbd_close,
+    .bdrv_create        = rbd_create,
+    .bdrv_get_info      = rbd_getinfo,
+    .create_options     = rbd_create_options,
+    .bdrv_getlength     = rbd_getlength,
+    .protocol_name      = "rbd",
+
+    .bdrv_aio_readv     = rbd_aio_readv,
+    .bdrv_aio_writev    = rbd_aio_writev,
+
+    .bdrv_snapshot_create = rbd_snap_create,
+    .bdrv_snapshot_list = rbd_snap_list,
+};
+
+static void bdrv_rbd_init(void)
+{
+    bdrv_register(&bdrv_rbd);
+}
+
+block_init(bdrv_rbd_init);
diff --git a/block/rbd_types.h b/block/rbd_types.h
new file mode 100644
index 0000000000..f4cca9970c
--- /dev/null
+++ b/block/rbd_types.h
@@ -0,0 +1,71 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.LIB.
+ *
+ */
+
+#ifndef CEPH_RBD_TYPES_H
+#define CEPH_RBD_TYPES_H
+
+
+/*
+ * rbd image 'foo' consists of objects
+ *   foo.rbd      - image metadata
+ *   foo.00000000
+ *   foo.00000001
+ *   ...          - data
+ */
+
+#define RBD_SUFFIX              ".rbd"
+#define RBD_DIRECTORY           "rbd_directory"
+#define RBD_INFO                "rbd_info"
+
+#define RBD_DEFAULT_OBJ_ORDER   22   /* 4MB */
+
+#define RBD_MAX_OBJ_NAME_SIZE   96
+#define RBD_MAX_BLOCK_NAME_SIZE 24
+#define RBD_MAX_SEG_NAME_SIZE   128
+
+#define RBD_COMP_NONE           0
+#define RBD_CRYPT_NONE          0
+
+#define RBD_HEADER_TEXT         "<<< Rados Block Device Image >>>\n"
+#define RBD_HEADER_SIGNATURE    "RBD"
+#define RBD_HEADER_VERSION      "001.005"
+
+struct rbd_info {
+    uint64_t max_id;
+} __attribute__ ((packed));
+
+struct rbd_obj_snap_ondisk {
+    uint64_t id;
+    uint64_t image_size;
+} __attribute__((packed));
+
+struct rbd_obj_header_ondisk {
+    char text[40];
+    char block_name[RBD_MAX_BLOCK_NAME_SIZE];
+    char signature[4];
+    char version[8];
+    struct {
+        uint8_t order;
+        uint8_t crypt_type;
+        uint8_t comp_type;
+        uint8_t unused;
+    } __attribute__((packed)) options;
+    uint64_t image_size;
+    uint64_t snap_seq;
+    uint32_t snap_count;
+    uint32_t reserved;
+    uint64_t snap_names_len;
+    struct rbd_obj_snap_ondisk snaps[0];
+} __attribute__((packed));
+
+
+#endif
diff --git a/block_int.h b/block_int.h
index 3c3adb5c85..6b3b09808b 100644
--- a/block_int.h
+++ b/block_int.h
@@ -29,7 +29,6 @@
 #include "qemu-queue.h"
 
 #define BLOCK_FLAG_ENCRYPT	1
-#define BLOCK_FLAG_COMPRESS	2
 #define BLOCK_FLAG_COMPAT6	4
 
 #define BLOCK_OPT_SIZE          "size"
@@ -227,6 +226,7 @@ typedef struct BlockConf {
     uint16_t logical_block_size;
     uint16_t min_io_size;
     uint32_t opt_io_size;
+    int32_t bootindex;
 } BlockConf;
 
 static inline unsigned int get_physical_block_exp(BlockConf *conf)
@@ -249,6 +249,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
     DEFINE_PROP_UINT16("physical_block_size", _state,                   \
                        _conf.physical_block_size, 512),                 \
     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
-    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
+    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
+    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)         \
 
 #endif /* BLOCK_INT_H */
diff --git a/configure b/configure
index 2917874f96..62defc41b8 100755
--- a/configure
+++ b/configure
@@ -332,6 +332,7 @@ zero_malloc=""
 trace_backend="nop"
 trace_file="trace"
 spice=""
+rbd=""
 
 # OS specific
 if check_define __linux__ ; then
@@ -741,6 +742,10 @@ for opt do
   ;;
   --*dir)
   ;;
+  --disable-rbd) rbd="no"
+  ;;
+  --enable-rbd) rbd="yes"
+  ;;
   *) echo "ERROR: unknown option $opt"; show_help="yes"
   ;;
   esac
@@ -934,6 +939,7 @@ echo "  --trace-file=NAME        Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
+echo "  --enable-rbd             enable building the rados block device (rbd)"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -1746,6 +1752,48 @@ if test "$mingw32" != yes -a "$pthread" = no; then
 fi
 
 ##########################################
+# rbd probe
+if test "$rbd" != "no" ; then
+  cat > $TMPC <<EOF
+#include <stdio.h>
+#include <rados/librados.h>
+int main(void) { rados_initialize(0, NULL); return 0; }
+EOF
+  rbd_libs="-lrados -lcrypto"
+  if compile_prog "" "$rbd_libs" ; then
+    librados_too_old=no
+    cat > $TMPC <<EOF
+#include <stdio.h>
+#include <rados/librados.h>
+#ifndef CEPH_OSD_TMAP_SET
+#error missing CEPH_OSD_TMAP_SET
+#endif
+int main(void) {
+    int (*func)(const rados_pool_t pool, uint64_t *snapid) = rados_selfmanaged_snap_create;
+    rados_initialize(0, NULL);
+    return 0;
+}
+EOF
+    if compile_prog "" "$rbd_libs" ; then
+      rbd=yes
+      libs_tools="$rbd_libs $libs_tools"
+      libs_softmmu="$rbd_libs $libs_softmmu"
+    else
+      rbd=no
+      librados_too_old=yes
+    fi
+  else
+    if test "$rbd" = "yes" ; then
+      feature_not_found "rados block device"
+    fi
+    rbd=no
+  fi
+  if test "$librados_too_old" = "yes" ; then
+    echo "-> Your librados version is too old - upgrade needed to have rbd support"
+  fi
+fi
+
+##########################################
 # linux-aio probe
 
 if test "$linux_aio" != "no" ; then
@@ -2354,6 +2402,7 @@ echo "vhost-net support $vhost_net"
 echo "Trace backend     $trace_backend"
 echo "Trace output file $trace_file-<pid>"
 echo "spice support     $spice"
+echo "rbd support       $rbd"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2627,6 +2676,9 @@ echo "CONFIG_UNAME_RELEASE=\"$uname_release\"" >> $config_host_mak
 if test "$zero_malloc" = "yes" ; then
   echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak
 fi
+if test "$rbd" = "yes" ; then
+  echo "CONFIG_RBD=y" >> $config_host_mak
+fi
 
 # USB host support
 case "$usb" in
diff --git a/cpu-common.h b/cpu-common.h
index bb6b137e16..6d4a898ad1 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -20,6 +20,12 @@
 
 #if !defined(CONFIG_USER_ONLY)
 
+enum device_endian {
+    DEVICE_NATIVE_ENDIAN,
+    DEVICE_BIG_ENDIAN,
+    DEVICE_LITTLE_ENDIAN,
+};
+
 /* address in the RAM (different from a physical address) */
 typedef unsigned long ram_addr_t;
 
@@ -55,7 +61,7 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque);
+                           void *opaque, enum device_endian endian);
 void cpu_unregister_io_memory(int table_address);
 
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
diff --git a/cpus.c b/cpus.c
index 91a0fb1146..0309189bfd 100644
--- a/cpus.c
+++ b/cpus.c
@@ -111,6 +111,8 @@ static void do_vm_stop(int reason)
         vm_running = 0;
         pause_all_vcpus();
         vm_state_notify(0, reason);
+        qemu_aio_flush();
+        bdrv_flush_all();
         monitor_protocol_event(QEVENT_STOP, NULL);
     }
 }
diff --git a/exec.c b/exec.c
index 42a35e00f9..a3384958c7 100644
--- a/exec.c
+++ b/exec.c
@@ -3331,7 +3331,8 @@ static subpage_t *subpage_init (target_phys_addr_t base, ram_addr_t *phys,
     mmio = qemu_mallocz(sizeof(subpage_t));
 
     mmio->base = base;
-    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
+    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio,
+                                            DEVICE_NATIVE_ENDIAN);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
@@ -3355,6 +3356,106 @@ static int get_free_io_mem_idx(void)
     return -1;
 }
 
+/*
+ * Usually, devices operate in little endian mode. There are devices out
+ * there that operate in big endian too. Each device gets byte swapped
+ * mmio if plugged onto a CPU that does the other endianness.
+ *
+ * CPU          Device           swap?
+ *
+ * little       little           no
+ * little       big              yes
+ * big          little           yes
+ * big          big              no
+ */
+
+typedef struct SwapEndianContainer {
+    CPUReadMemoryFunc *read[3];
+    CPUWriteMemoryFunc *write[3];
+    void *opaque;
+} SwapEndianContainer;
+
+static uint32_t swapendian_mem_readb (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+    SwapEndianContainer *c = opaque;
+    val = c->read[0](c->opaque, addr);
+    return val;
+}
+
+static uint32_t swapendian_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+    SwapEndianContainer *c = opaque;
+    val = bswap16(c->read[1](c->opaque, addr));
+    return val;
+}
+
+static uint32_t swapendian_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t val;
+    SwapEndianContainer *c = opaque;
+    val = bswap32(c->read[2](c->opaque, addr));
+    return val;
+}
+
+static CPUReadMemoryFunc * const swapendian_readfn[3]={
+    swapendian_mem_readb,
+    swapendian_mem_readw,
+    swapendian_mem_readl
+};
+
+static void swapendian_mem_writeb(void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    SwapEndianContainer *c = opaque;
+    c->write[0](c->opaque, addr, val);
+}
+
+static void swapendian_mem_writew(void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    SwapEndianContainer *c = opaque;
+    c->write[1](c->opaque, addr, bswap16(val));
+}
+
+static void swapendian_mem_writel(void *opaque, target_phys_addr_t addr,
+                                  uint32_t val)
+{
+    SwapEndianContainer *c = opaque;
+    c->write[2](c->opaque, addr, bswap32(val));
+}
+
+static CPUWriteMemoryFunc * const swapendian_writefn[3]={
+    swapendian_mem_writeb,
+    swapendian_mem_writew,
+    swapendian_mem_writel
+};
+
+static void swapendian_init(int io_index)
+{
+    SwapEndianContainer *c = qemu_malloc(sizeof(SwapEndianContainer));
+    int i;
+
+    /* Swap mmio for big endian targets */
+    c->opaque = io_mem_opaque[io_index];
+    for (i = 0; i < 3; i++) {
+        c->read[i] = io_mem_read[io_index][i];
+        c->write[i] = io_mem_write[io_index][i];
+
+        io_mem_read[io_index][i] = swapendian_readfn[i];
+        io_mem_write[io_index][i] = swapendian_writefn[i];
+    }
+    io_mem_opaque[io_index] = c;
+}
+
+static void swapendian_del(int io_index)
+{
+    if (io_mem_read[io_index][0] == swapendian_readfn[0]) {
+        qemu_free(io_mem_opaque[io_index]);
+    }
+}
+
 /* mem_read and mem_write are arrays of functions containing the
    function to access byte (index 0), word (index 1) and dword (index
    2). Functions can be omitted with a NULL function pointer.
@@ -3365,7 +3466,7 @@ static int get_free_io_mem_idx(void)
 static int cpu_register_io_memory_fixed(int io_index,
                                         CPUReadMemoryFunc * const *mem_read,
                                         CPUWriteMemoryFunc * const *mem_write,
-                                        void *opaque)
+                                        void *opaque, enum device_endian endian)
 {
     int i;
 
@@ -3389,14 +3490,30 @@ static int cpu_register_io_memory_fixed(int io_index,
     }
     io_mem_opaque[io_index] = opaque;
 
+    switch (endian) {
+    case DEVICE_BIG_ENDIAN:
+#ifndef TARGET_WORDS_BIGENDIAN
+        swapendian_init(io_index);
+#endif
+        break;
+    case DEVICE_LITTLE_ENDIAN:
+#ifdef TARGET_WORDS_BIGENDIAN
+        swapendian_init(io_index);
+#endif
+        break;
+    case DEVICE_NATIVE_ENDIAN:
+    default:
+        break;
+    }
+
     return (io_index << IO_MEM_SHIFT);
 }
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque)
+                           void *opaque, enum device_endian endian)
 {
-    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
+    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque, endian);
 }
 
 void cpu_unregister_io_memory(int io_table_address)
@@ -3404,6 +3521,8 @@ void cpu_unregister_io_memory(int io_table_address)
     int i;
     int io_index = io_table_address >> IO_MEM_SHIFT;
 
+    swapendian_del(io_index);
+
     for (i=0;i < 3; i++) {
         io_mem_read[io_index][i] = unassigned_mem_read[i];
         io_mem_write[io_index][i] = unassigned_mem_write[i];
@@ -3416,14 +3535,21 @@ static void io_mem_init(void)
 {
     int i;
 
-    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read, unassigned_mem_write, NULL);
-    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read, unassigned_mem_write, NULL);
-    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read, notdirty_mem_write, NULL);
+    cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
+                                 unassigned_mem_write, NULL,
+                                 DEVICE_NATIVE_ENDIAN);
+    cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
+                                 unassigned_mem_write, NULL,
+                                 DEVICE_NATIVE_ENDIAN);
+    cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
+                                 notdirty_mem_write, NULL,
+                                 DEVICE_NATIVE_ENDIAN);
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
     io_mem_watch = cpu_register_io_memory(watch_mem_read,
-                                          watch_mem_write, NULL);
+                                          watch_mem_write, NULL,
+                                          DEVICE_NATIVE_ENDIAN);
 }
 
 #endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index c619112b12..84e9af76a2 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -410,21 +410,24 @@ static int pci_pbm_init_device(SysBusDevice *dev)
 
     /* apb_config */
     apb_config = cpu_register_io_memory(apb_config_read,
-                                        apb_config_write, s);
+                                        apb_config_write, s,
+                                        DEVICE_NATIVE_ENDIAN);
     /* at region 0 */
     sysbus_init_mmio(dev, 0x10000ULL, apb_config);
 
     /* PCI configuration space */
     s->pci_config_handler.read = apb_pci_config_read;
     s->pci_config_handler.write = apb_pci_config_write;
-    pci_config = cpu_register_io_memory_simple(&s->pci_config_handler);
+    pci_config = cpu_register_io_memory_simple(&s->pci_config_handler,
+                                               DEVICE_NATIVE_ENDIAN);
     assert(pci_config >= 0);
     /* at region 1 */
     sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
 
     /* pci_ioport */
     pci_ioport = cpu_register_io_memory(pci_apb_ioread,
-                                        pci_apb_iowrite, s);
+                                        pci_apb_iowrite, s,
+                                        DEVICE_NATIVE_ENDIAN);
     /* at region 2 */
     sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
 
diff --git a/hw/apic.c b/hw/apic.c
index 5f4a87c807..a5a53fb963 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -980,7 +980,8 @@ static int apic_init1(SysBusDevice *dev)
         return -1;
     }
     apic_io_memory = cpu_register_io_memory(apic_mem_read,
-                                            apic_mem_write, NULL);
+                                            apic_mem_write, NULL,
+                                            DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MSI_ADDR_SIZE, apic_io_memory);
 
     s->timer = qemu_new_timer(vm_clock, apic_timer, s);
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 8286a282ea..e6b195324b 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -742,7 +742,8 @@ static void gic_init(gic_state *s)
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
     s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
-                                          gic_dist_writefn, s);
+                                          gic_dist_writefn, s,
+                                          DEVICE_NATIVE_ENDIAN);
     gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 }
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 0cb2ffc505..bd0664fe7a 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -208,7 +208,8 @@ static int arm_sysctl_init1(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(arm_sysctl_readfn,
-                                       arm_sysctl_writefn, s);
+                                       arm_sysctl_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? Save/restore.  */
     return 0;
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index f009e9e51d..82f05dec84 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -269,7 +269,7 @@ static int sp804_init(SysBusDevice *dev)
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     iomemtype = cpu_register_io_memory(sp804_readfn,
-                                       sp804_writefn, s);
+                                       sp804_writefn, s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
     return 0;
@@ -340,7 +340,8 @@ static int icp_pit_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->timer[2]->irq);
 
     iomemtype = cpu_register_io_memory(icp_pit_readfn,
-                                       icp_pit_writefn, s);
+                                       icp_pit_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* This device has no state to save/restore.  The component timers will
        save themselves.  */
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 588ec9805c..304cd34bc2 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -130,7 +130,7 @@ static int bitband_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
-                                       &s->base);
+                                       &s->base, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x02000000, iomemtype);
     return 0;
 }
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index f16c76aee2..57b5e2f041 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -280,11 +280,13 @@ void axisdev88_init (ram_addr_t ram_size,
 
       /* Attach a NAND flash to CS1.  */
     nand_state.nand = nand_init(NAND_MFR_STMICRO, 0x39);
-    nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state);
+    nand_regs = cpu_register_io_memory(nand_read, nand_write, &nand_state,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x10000000, 0x05000000, nand_regs);
 
     gpio_state.nand = &nand_state;
-    gpio_regs = cpu_register_io_memory(gpio_read, gpio_write, &gpio_state);
+    gpio_regs = cpu_register_io_memory(gpio_read, gpio_write, &gpio_state,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x3001a000, 0x5c, gpio_regs);
 
 
diff --git a/hw/bonito.c b/hw/bonito.c
index dcf031134e..65a4a637bf 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -698,7 +698,8 @@ static int bonito_initfn(PCIDevice *dev)
     pci_config_set_revision(dev->config, 0x01);
 
     /* set the north bridge register mapping */
-    s->bonito_reg_handle = cpu_register_io_memory(bonito_read, bonito_write, s);
+    s->bonito_reg_handle = cpu_register_io_memory(bonito_read, bonito_write, s,
+                                                  DEVICE_NATIVE_ENDIAN);
     s->bonito_reg_start = BONITO_INTERNAL_REG_BASE;
     s->bonito_reg_length = BONITO_INTERNAL_REG_SIZE;
     cpu_register_physical_memory(s->bonito_reg_start, s->bonito_reg_length,
@@ -706,7 +707,8 @@ static int bonito_initfn(PCIDevice *dev)
 
     /* set the north bridge pci configure  mapping */
     s->bonito_pciconf_handle = cpu_register_io_memory(bonito_pciconf_read,
-                                                      bonito_pciconf_write, s);
+                                                      bonito_pciconf_write, s,
+                                                      DEVICE_NATIVE_ENDIAN);
     s->bonito_pciconf_start = BONITO_PCICONFIG_BASE;
     s->bonito_pciconf_length = BONITO_PCICONFIG_SIZE;
     cpu_register_physical_memory(s->bonito_pciconf_start, s->bonito_pciconf_length,
@@ -714,21 +716,24 @@ static int bonito_initfn(PCIDevice *dev)
 
     /* set the south bridge pci configure  mapping */
     s->bonito_spciconf_handle = cpu_register_io_memory(bonito_spciconf_read,
-                                                       bonito_spciconf_write, s);
+                                                       bonito_spciconf_write, s,
+                                                       DEVICE_NATIVE_ENDIAN);
     s->bonito_spciconf_start = BONITO_SPCICONFIG_BASE;
     s->bonito_spciconf_length = BONITO_SPCICONFIG_SIZE;
     cpu_register_physical_memory(s->bonito_spciconf_start, s->bonito_spciconf_length,
                                  s->bonito_spciconf_handle);
 
     s->bonito_ldma_handle = cpu_register_io_memory(bonito_ldma_read,
-                                                   bonito_ldma_write, s);
+                                                   bonito_ldma_write, s,
+                                                   DEVICE_NATIVE_ENDIAN);
     s->bonito_ldma_start = 0xbfe00200;
     s->bonito_ldma_length = 0x100;
     cpu_register_physical_memory(s->bonito_ldma_start, s->bonito_ldma_length,
                                  s->bonito_ldma_handle);
 
     s->bonito_cop_handle = cpu_register_io_memory(bonito_cop_read,
-                                                  bonito_cop_write, s);
+                                                  bonito_cop_write, s,
+                                                  DEVICE_NATIVE_ENDIAN);
     s->bonito_cop_start = 0xbfe00300;
     s->bonito_cop_length = 0x100;
     cpu_register_physical_memory(s->bonito_cop_start, s->bonito_cop_length,
@@ -738,12 +743,12 @@ static int bonito_initfn(PCIDevice *dev)
     s->bonito_pciio_start = BONITO_PCIIO_BASE;
     s->bonito_pciio_length = BONITO_PCIIO_SIZE;
     isa_mem_base = s->bonito_pciio_start;
-    isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length, 0);
+    isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length);
 
     /* add pci local io mapping */
     s->bonito_localio_start = BONITO_DEV_BASE;
     s->bonito_localio_length = BONITO_DEV_SIZE;
-    isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length, 0);
+    isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length);
 
     /* set the default value of north bridge pci config */
     pci_set_word(dev->config + PCI_COMMAND, 0x0000);
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 40be55d1b1..4f5040cf4b 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3076,23 +3076,27 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
 
     s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
-                                                  cirrus_vga_mem_write, s);
+                                                  cirrus_vga_mem_write, s,
+                                                  DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
                                  s->vga.vga_io_memory);
     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
 
     /* I/O handler for LFB */
     s->cirrus_linear_io_addr =
-        cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s);
+        cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
+                               DEVICE_NATIVE_ENDIAN);
 
     /* I/O handler for LFB */
     s->cirrus_linear_bitblt_io_addr =
         cpu_register_io_memory(cirrus_linear_bitblt_read,
-                               cirrus_linear_bitblt_write, s);
+                               cirrus_linear_bitblt_write, s,
+                               DEVICE_NATIVE_ENDIAN);
 
     /* I/O handler for memory-mapped I/O */
     s->cirrus_mmio_io_addr =
-        cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s);
+        cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
+                               DEVICE_NATIVE_ENDIAN);
 
     s->real_vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
diff --git a/hw/cs4231.c b/hw/cs4231.c
index 2977101e39..a65b697a19 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -148,7 +148,8 @@ static int cs4231_init1(SysBusDevice *dev)
     int io;
     CSState *s = FROM_SYSBUS(CSState, dev);
 
-    io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s);
+    io = cpu_register_io_memory(cs_mem_read, cs_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, CS_SIZE, io);
     sysbus_init_irq(dev, &s->irq);
 
diff --git a/hw/cs4231a.c b/hw/cs4231a.c
index 4d5ce5c277..598f0322d9 100644
--- a/hw/cs4231a.c
+++ b/hw/cs4231a.c
@@ -645,6 +645,7 @@ static int cs4231a_initfn (ISADevice *dev)
     isa_init_irq (dev, &s->pic, s->irq);
 
     for (i = 0; i < 4; i++) {
+        isa_init_ioport(dev, i);
         register_ioport_write (s->port + i, 1, 1, cs_write, s);
         register_ioport_read (s->port + i, 1, 1, cs_read, s);
     }
diff --git a/hw/cuda.c b/hw/cuda.c
index 3f238b630c..e4c178dd2a 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -762,7 +762,8 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
     s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
 
     s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
-    *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s);
+    *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
+                                             DEVICE_NATIVE_ENDIAN);
     register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
     qemu_register_reset(cuda_reset, s);
 }
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index aa07ab7d84..bf88f2ac80 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -96,8 +96,10 @@ static int pci_dec_21154_init_device(SysBusDevice *dev)
 
     s = FROM_SYSBUS(DECState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
+    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
+                                               DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index e65e4d1535..0ef8abe839 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -908,6 +908,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     qemu_register_reset(nic_reset, s);
     nic_reset(s);
 
-    s->mmio_index = cpu_register_io_memory(dp8393x_read, dp8393x_write, s);
+    s->mmio_index = cpu_register_io_memory(dp8393x_read, dp8393x_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index);
 }
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index 009d127455..b1c52321fe 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -171,10 +171,12 @@ void *ds1225y_init(target_phys_addr_t mem_base, const char *filename)
     }
 
     /* Read/write memory */
-    mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s);
+    mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW);
     /* Read/write protected memory */
-    mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s);
+    mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP);
     return s;
 }
diff --git a/hw/e1000.c b/hw/e1000.c
index 57d08cfa35..af101bd7b7 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -30,6 +30,7 @@
 #include "net.h"
 #include "net/checksum.h"
 #include "loader.h"
+#include "sysemu.h"
 
 #include "e1000_hw.h"
 
@@ -857,9 +858,6 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
     E1000State *s = opaque;
     unsigned int index = (addr & 0x1ffff) >> 2;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
     if (index < NWRITEOPS && macreg_writeops[index]) {
         macreg_writeops[index](s, index, val);
     } else if (index < NREADOPS && macreg_readops[index]) {
@@ -894,11 +892,7 @@ e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
 
     if (index < NREADOPS && macreg_readops[index])
     {
-        uint32_t val = macreg_readops[index](s, index);
-#ifdef TARGET_WORDS_BIGENDIAN
-        val = bswap32(val);
-#endif
-        return val;
+        return macreg_readops[index](s, index);
     }
     DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2);
     return 0;
@@ -1131,7 +1125,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
     pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
 
     d->mmio_index = cpu_register_io_memory(e1000_mmio_read,
-            e1000_mmio_write, d);
+            e1000_mmio_write, d, DEVICE_LITTLE_ENDIAN);
 
     pci_register_bar(&d->dev, 0, PNPMMIO_SIZE,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
@@ -1154,6 +1148,9 @@ static int pci_e1000_init(PCIDevice *pci_dev)
                           d->dev.qdev.info->name, d->dev.qdev.id, d);
 
     qemu_format_nic_info_str(&d->nic->nc, macaddr);
+
+    add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+
     return 0;
 }
 
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index a8042e94bc..2bda87b6c9 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -297,12 +297,14 @@ static int ecc_init1(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     s->regs[0] = s->version;
-    ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s);
+    ecc_io_memory = cpu_register_io_memory(ecc_mem_read, ecc_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, ECC_SIZE, ecc_io_memory);
 
     if (s->version == ECC_MCC) { // SS-600MP only
         ecc_io_memory = cpu_register_io_memory(ecc_diag_mem_read,
-                                               ecc_diag_mem_write, s);
+                                               ecc_diag_mem_write, s,
+                                               DEVICE_NATIVE_ENDIAN);
         sysbus_init_mmio(dev, ECC_DIAG_SIZE, ecc_io_memory);
     }
 
diff --git a/hw/eepro100.c b/hw/eepro100.c
index f8a700a2b8..edf48f61d1 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -46,6 +46,7 @@
 #include "pci.h"
 #include "net.h"
 #include "eeprom93xx.h"
+#include "sysemu.h"
 
 #define KiB 1024
 
@@ -1878,7 +1879,8 @@ static int e100_nic_init(PCIDevice *pci_dev)
 
     /* Handler for memory-mapped I/O */
     s->mmio_index =
-        cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s);
+        cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
+                               DEVICE_NATIVE_ENDIAN);
 
     pci_register_bar(&s->dev, 0, PCI_MEM_SIZE,
                            PCI_BASE_ADDRESS_SPACE_MEMORY |
@@ -1907,6 +1909,8 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate->name = s->nic->nc.model;
     vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
 
+    add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+
     return 0;
 }
 
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index ac1f6ebbf5..664b8d9c4d 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -73,7 +73,8 @@ static int empty_slot_init1(SysBusDevice *dev)
     ram_addr_t empty_slot_offset;
 
     empty_slot_offset = cpu_register_io_memory(empty_slot_read,
-                                               empty_slot_write, s);
+                                               empty_slot_write, s,
+                                               DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, s->size, empty_slot_offset | IO_MEM_RAM);
     return 0;
 }
diff --git a/hw/escc.c b/hw/escc.c
index 8714239780..ba6063608d 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -914,7 +914,8 @@ static int escc_init1(SysBusDevice *dev)
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
 
-    io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s);
+    io = cpu_register_io_memory(escc_mem_read, escc_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, ESCC_SIZE << s->it_shift, io);
     s->mmio_index = io;
 
diff --git a/hw/esp.c b/hw/esp.c
index 910fd31665..fa9d2a2706 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -722,7 +722,8 @@ static int esp_init1(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     assert(s->it_shift != -1);
 
-    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
+    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
 
     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c
index 15c8ad3dc5..c205ec1b8f 100644
--- a/hw/etraxfs_dma.c
+++ b/hw/etraxfs_dma.c
@@ -750,7 +750,7 @@ void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
 	ctrl->nr_channels = nr_channels;
 	ctrl->channels = qemu_mallocz(sizeof ctrl->channels[0] * nr_channels);
 
-	ctrl->map = cpu_register_io_memory(dma_read, dma_write, ctrl);
+	ctrl->map = cpu_register_io_memory(dma_read, dma_write, ctrl, DEVICE_NATIVE_ENDIAN);
 	cpu_register_physical_memory(base, nr_channels * 0x2000, ctrl->map);
 	return ctrl;
 }
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index ade96f14ac..6aa4007203 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -598,7 +598,8 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
 	tdk_init(&eth->phy);
 	mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
 
-	eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth);
+	eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth,
+                                              DEVICE_NATIVE_ENDIAN);
 	cpu_register_physical_memory (base, 0x5c, eth->ethregs);
 
 	memcpy(eth->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index b2c4859949..4feffda608 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -145,7 +145,8 @@ static int etraxfs_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_nmi);
 
-    intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s);
+    intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s,
+                                            DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
     return 0;
 }
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 336cc5476b..2787ebd5c8 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -200,7 +200,8 @@ static int etraxfs_ser_init(SysBusDevice *dev)
     s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
 
     sysbus_init_irq(dev, &s->irq);
-    ser_regs = cpu_register_io_memory(ser_read, ser_write, s);
+    ser_regs = cpu_register_io_memory(ser_read, ser_write, s,
+                                      DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index 87700d4cdf..ba1adbe3c0 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -323,7 +323,8 @@ static int etraxfs_timer_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &t->irq);
     sysbus_init_irq(dev, &t->nmi);
 
-    timer_regs = cpu_register_io_memory(timer_read, timer_write, t);
+    timer_regs = cpu_register_io_memory(timer_read, timer_write, t,
+                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x5c, timer_regs);
 
     qemu_register_reset(etraxfs_timer_reset, t);
diff --git a/hw/fdc.c b/hw/fdc.c
index c159dcb630..4bbcc4715f 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -35,6 +35,7 @@
 #include "sysbus.h"
 #include "qdev-addr.h"
 #include "blockdev.h"
+#include "sysemu.h"
 
 /********************************************************/
 /* debug Floppy devices */
@@ -523,6 +524,8 @@ typedef struct FDCtrlSysBus {
 typedef struct FDCtrlISABus {
     ISADevice busdev;
     struct FDCtrl state;
+    int32_t bootindexA;
+    int32_t bootindexB;
 } FDCtrlISABus;
 
 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
@@ -1983,12 +1986,18 @@ static int isabus_fdc_init1(ISADevice *dev)
                           &fdctrl_write_port, fdctrl);
     register_ioport_write(iobase + 0x07, 1, 1,
                           &fdctrl_write_port, fdctrl);
+    isa_init_ioport_range(dev, iobase, 6);
+    isa_init_ioport(dev, iobase + 7);
+
     isa_init_irq(&isa->busdev, &fdctrl->irq, isairq);
     fdctrl->dma_chann = dma_chann;
 
     qdev_set_legacy_instance_id(&dev->qdev, iobase, 2);
     ret = fdctrl_init_common(fdctrl);
 
+    add_boot_device_path(isa->bootindexA, &dev->qdev, "/floppy@0");
+    add_boot_device_path(isa->bootindexB, &dev->qdev, "/floppy@1");
+
     return ret;
 }
 
@@ -1999,7 +2008,8 @@ static int sysbus_fdc_init1(SysBusDevice *dev)
     int io;
     int ret;
 
-    io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl);
+    io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x08, io);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
@@ -2017,7 +2027,8 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
     int io;
 
     io = cpu_register_io_memory(fdctrl_mem_read_strict,
-                                fdctrl_mem_write_strict, fdctrl);
+                                fdctrl_mem_write_strict, fdctrl,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x08, io);
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
@@ -2040,6 +2051,7 @@ static const VMStateDescription vmstate_isa_fdc ={
 static ISADeviceInfo isa_fdc_info = {
     .init = isabus_fdc_init1,
     .qdev.name  = "isa-fdc",
+    .qdev.fw_name  = "fdc",
     .qdev.size  = sizeof(FDCtrlISABus),
     .qdev.no_user = 1,
     .qdev.vmsd  = &vmstate_isa_fdc,
@@ -2047,6 +2059,8 @@ static ISADeviceInfo isa_fdc_info = {
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
         DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
+        DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
+        DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 21d60b5855..c7731c2993 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -86,7 +86,7 @@ typedef struct FileOperations
     int (*fstat)(FsContext *, int, struct stat *);
     int (*rename)(FsContext *, const char *, const char *);
     int (*truncate)(FsContext *, const char *, off_t);
-    int (*fsync)(FsContext *, int);
+    int (*fsync)(FsContext *, int, int);
     int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf);
     ssize_t (*lgetxattr)(FsContext *, const char *,
                          const char *, void *, size_t);
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 72866aea95..85c8c3c7bf 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -53,6 +53,7 @@ struct FWCfgState {
     FWCfgFiles *files;
     uint16_t cur_entry;
     uint32_t cur_offset;
+    Notifier machine_ready;
 };
 
 static void fw_cfg_write(FWCfgState *s, uint8_t value)
@@ -277,10 +278,9 @@ int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
     return 1;
 }
 
-int fw_cfg_add_file(FWCfgState *s,  const char *dir, const char *filename,
-                    uint8_t *data, uint32_t len)
+int fw_cfg_add_file(FWCfgState *s,  const char *filename, uint8_t *data,
+                    uint32_t len)
 {
-    const char *basename;
     int i, index;
 
     if (!s->files) {
@@ -297,15 +297,8 @@ int fw_cfg_add_file(FWCfgState *s,  const char *dir, const char *filename,
 
     fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
 
-    basename = strrchr(filename, '/');
-    if (basename) {
-        basename++;
-    } else {
-        basename = filename;
-    }
-
-    snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
-             "%s/%s", dir, basename);
+    pstrcpy(s->files->f[index].name, sizeof(s->files->f[index].name),
+            filename);
     for (i = 0; i < index; i++) {
         if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) {
             FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__,
@@ -323,6 +316,15 @@ int fw_cfg_add_file(FWCfgState *s,  const char *dir, const char *filename,
     return 1;
 }
 
+static void fw_cfg_machine_ready(struct Notifier* n)
+{
+    uint32_t len;
+    FWCfgState *s = container_of(n, FWCfgState, machine_ready);
+    char *bootindex = get_boot_devices_list(&len);
+
+    fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
+}
+
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
                         target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
 {
@@ -351,6 +353,10 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
     fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
 
+
+    s->machine_ready.notify = fw_cfg_machine_ready;
+    qemu_add_machine_init_done_notifier(&s->machine_ready);
+
     return s;
 }
 
@@ -360,11 +366,13 @@ static int fw_cfg_init1(SysBusDevice *dev)
     int io_ctl_memory, io_data_memory;
 
     io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
-                                           fw_cfg_ctl_mem_write, s);
+                                           fw_cfg_ctl_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
 
     io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
-                                            fw_cfg_data_mem_write, s);
+                                            fw_cfg_data_mem_write, s,
+                                            DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
 
     if (s->ctl_iobase) {
diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
index 4d13a4f394..856bf9199d 100644
--- a/hw/fw_cfg.h
+++ b/hw/fw_cfg.h
@@ -60,8 +60,8 @@ int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
 int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
 int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
                         void *callback_opaque, uint8_t *data, size_t len);
-int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
-                    uint8_t *data, uint32_t len);
+int fw_cfg_add_file(FWCfgState *s, const char *filename, uint8_t *data,
+                    uint32_t len);
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
                         target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
 
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 3c8fb982dc..a41e988799 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -607,7 +607,8 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
 
     cpu_register_physical_memory(vram_base, s->vram_size, s->vram_offset);
 
-    io_ctrl = cpu_register_io_memory(g364fb_ctrl_read, g364fb_ctrl_write, s);
+    io_ctrl = cpu_register_io_memory(g364fb_ctrl_read, g364fb_ctrl_write, s,
+                                     DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(ctrl_base, 0x200000, io_ctrl);
 
     return 0;
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 91c755f4d7..bd3d6b0d9f 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -108,8 +108,10 @@ static int pci_grackle_init_device(SysBusDevice *dev)
 
     s = FROM_SYSBUS(GrackleState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
+    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
+                                               DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index cabf7ea0bf..14c6ad364c 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -297,11 +297,7 @@ static void gt64120_pci_mapping(GT64120State *s)
       s->PCI0IO_start = s->regs[GT_PCI0IOLD] << 21;
       s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
       isa_mem_base = s->PCI0IO_start;
-#ifdef TARGET_WORDS_BIGENDIAN
-      isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length, 1);
-#else
-      isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length, 0);
-#endif
+      isa_mmio_init(s->PCI0IO_start, s->PCI0IO_length);
     }
 }
 
@@ -1116,7 +1112,8 @@ PCIBus *pci_gt64120_init(qemu_irq *pic)
     s->pci->bus = pci_register_bus(NULL, "pci",
                                    pci_gt64120_set_irq, pci_gt64120_map_irq,
                                    pic, PCI_DEVFN(18, 0), 4);
-    s->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, s);
+    s->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
                             0, NULL, NULL);
 
diff --git a/hw/gus.c b/hw/gus.c
index e9016d8105..ff9e7c7e3b 100644
--- a/hw/gus.c
+++ b/hw/gus.c
@@ -264,20 +264,24 @@ static int gus_initfn (ISADevice *dev)
 
     register_ioport_write (s->port, 1, 1, gus_writeb, s);
     register_ioport_write (s->port, 1, 2, gus_writew, s);
+    isa_init_ioport_range(dev, s->port, 2);
 
     register_ioport_read ((s->port + 0x100) & 0xf00, 1, 1, gus_readb, s);
     register_ioport_read ((s->port + 0x100) & 0xf00, 1, 2, gus_readw, s);
+    isa_init_ioport_range(dev, (s->port + 0x100) & 0xf00, 2);
 
     register_ioport_write (s->port + 6, 10, 1, gus_writeb, s);
     register_ioport_write (s->port + 6, 10, 2, gus_writew, s);
     register_ioport_read (s->port + 6, 10, 1, gus_readb, s);
     register_ioport_read (s->port + 6, 10, 2, gus_readw, s);
+    isa_init_ioport_range(dev, s->port + 6, 10);
 
 
     register_ioport_write (s->port + 0x100, 8, 1, gus_writeb, s);
     register_ioport_write (s->port + 0x100, 8, 2, gus_writew, s);
     register_ioport_read (s->port + 0x100, 8, 1, gus_readb, s);
     register_ioport_read (s->port + 0x100, 8, 2, gus_readw, s);
+    isa_init_ioport_range(dev, s->port + 0x100, 8);
 
     DMA_register_channel (s->emu.gusdma, GUS_read_DMA, s);
     s->emu.himemaddr = s->himem;
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index cd86121096..b19b754b31 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -68,7 +68,6 @@ static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
     HeathrowPIC *pic;
     unsigned int n;
 
-    value = bswap32(value);
     n = ((addr & 0xfff) - 0x10) >> 4;
     PIC_DPRINTF("writel: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
     if (n >= 2)
@@ -118,7 +117,6 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
         }
     }
     PIC_DPRINTF("readl: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
-    value = bswap32(value);
     return value;
 }
 
@@ -222,7 +220,8 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
     s = qemu_mallocz(sizeof(HeathrowPICS));
     /* only 1 CPU */
     s->irqs = irqs[0];
-    *pmem_index = cpu_register_io_memory(pic_read, pic_write, s);
+    *pmem_index = cpu_register_io_memory(pic_read, pic_write, s,
+                                         DEVICE_LITTLE_ENDIAN);
 
     register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
                     heathrow_pic_load, s);
diff --git a/hw/hpet.c b/hw/hpet.c
index d5c406cca0..8fb6811a2c 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -720,7 +720,8 @@ static int hpet_init(SysBusDevice *dev)
 
     /* HPET Area */
     iomemtype = cpu_register_io_memory(hpet_ram_read,
-                                       hpet_ram_write, s);
+                                       hpet_ram_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x400, iomemtype);
     return 0;
 }
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index dfe6091e75..ea5d2dc84f 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -253,8 +253,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
     pci_conf[PCI_INTERRUPT_PIN] = 0x01; // interrupt on pin 1
 
     irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
-    ide_bus_new(&d->bus[0], &d->dev.qdev);
-    ide_bus_new(&d->bus[1], &d->dev.qdev);
+    ide_bus_new(&d->bus[0], &d->dev.qdev, 0);
+    ide_bus_new(&d->bus[1], &d->dev.qdev, 1);
     ide_init2(&d->bus[0], irq[0]);
     ide_init2(&d->bus[1], irq[1]);
 
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 85f4a1607b..71af66fff6 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -449,6 +449,7 @@ struct IDEBus {
     IDEDevice *slave;
     BMDMAState *bmdma;
     IDEState ifs[2];
+    int bus_id;
     uint8_t unit;
     uint8_t cmd;
     qemu_irq irq;
@@ -567,7 +568,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
 
 /* hw/ide/qdev.c */
-void ide_bus_new(IDEBus *idebus, DeviceState *dev);
+void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id);
 IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
 
 #endif /* HW_IDE_INTERNAL_H */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 6b57e0d301..8c59c5a47c 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -67,9 +67,11 @@ static int isa_ide_initfn(ISADevice *dev)
 {
     ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev);
 
-    ide_bus_new(&s->bus, &s->dev.qdev);
+    ide_bus_new(&s->bus, &s->dev.qdev, 0);
     ide_init_ioport(&s->bus, s->iobase, s->iobase2);
     isa_init_irq(dev, &s->irq, s->isairq);
+    isa_init_ioport_range(dev, s->iobase, 8);
+    isa_init_ioport(dev, s->iobase2);
     ide_init2(&s->bus, s->irq);
     vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s);
     return 0;
@@ -98,6 +100,7 @@ ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
 
 static ISADeviceInfo isa_ide_info = {
     .qdev.name  = "isa-ide",
+    .qdev.fw_name  = "ide",
     .qdev.size  = sizeof(ISAIDEState),
     .init       = isa_ide_initfn,
     .qdev.reset = isa_ide_reset,
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index bd1c73e62b..c1b4caab5b 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -320,7 +320,8 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
         DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
 
     pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
-                                             pmac_ide_write, d);
+                                             pmac_ide_write, d,
+                                             DEVICE_NATIVE_ENDIAN);
     vmstate_register(NULL, 0, &vmstate_pmac, d);
     qemu_register_reset(pmac_ide_reset, d);
 
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 9f20e8bab6..82b24b673b 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -129,8 +129,10 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
 
     s->shift = shift;
 
-    mem1 = cpu_register_io_memory(mmio_ide_reads, mmio_ide_writes, s);
-    mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s);
+    mem1 = cpu_register_io_memory(mmio_ide_reads, mmio_ide_writes, s,
+                                  DEVICE_NATIVE_ENDIAN);
+    mem2 = cpu_register_io_memory(mmio_ide_status, mmio_ide_cmd, s,
+                                  DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(membase, 16 << shift, mem1);
     cpu_register_physical_memory(membase2, 2 << shift, mem2);
     vmstate_register(NULL, 0, &vmstate_ide_mmio, s);
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index e02b89a38c..1c0cb0cda4 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -125,8 +125,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
 
     vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
 
-    ide_bus_new(&d->bus[0], &d->dev.qdev);
-    ide_bus_new(&d->bus[1], &d->dev.qdev);
+    ide_bus_new(&d->bus[0], &d->dev.qdev, 0);
+    ide_bus_new(&d->bus[1], &d->dev.qdev, 1);
     ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->bus[1], 0x170, 0x376);
 
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 080876035f..2bb5c27341 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -21,17 +21,32 @@
 #include "qemu-error.h"
 #include <hw/ide/internal.h>
 #include "blockdev.h"
+#include "sysemu.h"
 
 /* --------------------------------- */
 
+static char *idebus_get_fw_dev_path(DeviceState *dev);
+
 static struct BusInfo ide_bus_info = {
     .name  = "IDE",
     .size  = sizeof(IDEBus),
+    .get_fw_dev_path = idebus_get_fw_dev_path,
 };
 
-void ide_bus_new(IDEBus *idebus, DeviceState *dev)
+void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id)
 {
     qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL);
+    idebus->bus_id = bus_id;
+}
+
+static char *idebus_get_fw_dev_path(DeviceState *dev)
+{
+    char path[30];
+
+    snprintf(path, sizeof(path), "%s@%d", qdev_fw_name(dev),
+             ((IDEBus*)dev->parent_bus)->bus_id);
+
+    return strdup(path);
 }
 
 static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base)
@@ -129,11 +144,16 @@ static int ide_drive_initfn(IDEDevice *dev)
     if (!dev->serial) {
         dev->serial = qemu_strdup(s->drive_serial_str);
     }
+
+    add_boot_device_path(dev->conf.bootindex, &dev->qdev,
+                         dev->unit ? "/disk@1" : "/disk@0");
+
     return 0;
 }
 
 static IDEDeviceInfo ide_drive_info = {
     .qdev.name  = "ide-drive",
+    .qdev.fw_name  = "drive",
     .qdev.size  = sizeof(IDEDrive),
     .init       = ide_drive_initfn,
     .qdev.props = (Property[]) {
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 66be0c4cce..78857e8020 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -154,8 +154,8 @@ static int vt82c686b_ide_initfn(PCIDevice *dev)
 
     vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
 
-    ide_bus_new(&d->bus[0], &d->dev.qdev);
-    ide_bus_new(&d->bus[1], &d->dev.qdev);
+    ide_bus_new(&d->bus[0], &d->dev.qdev, 0);
+    ide_bus_new(&d->bus[1], &d->dev.qdev, 1);
     ide_init2(&d->bus[0], isa_reserve_irq(14));
     ide_init2(&d->bus[1], isa_reserve_irq(15));
     ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 3bf216bf85..b049940821 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -256,7 +256,8 @@ static int integratorcm_init(SysBusDevice *dev)
     s->flash_offset = qemu_ram_alloc(NULL, "integrator.flash", 0x100000);
 
     iomemtype = cpu_register_io_memory(integratorcm_readfn,
-                                       integratorcm_writefn, s);
+                                       integratorcm_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x00800000, iomemtype);
     integratorcm_do_remap(s, 1);
     /* ??? Save/restore.  */
@@ -382,7 +383,8 @@ static int icp_pic_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_fiq);
     iomemtype = cpu_register_io_memory(icp_pic_readfn,
-                                       icp_pic_writefn, s);
+                                       icp_pic_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x00800000, iomemtype);
     return 0;
 }
@@ -435,7 +437,8 @@ static void icp_control_init(uint32_t base)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(icp_control_readfn,
-                                       icp_control_writefn, NULL);
+                                       icp_control_writefn, NULL,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00800000, iomemtype);
     /* ??? Save/restore.  */
 }
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index fe316245ad..b2b67082e7 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -1156,7 +1156,8 @@ static int intel_hda_init(PCIDevice *pci)
     conf[0x40] = 0x01;
 
     d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read,
-                                          intel_hda_mmio_write, d);
+                                          intel_hda_mmio_write, d,
+                                          DEVICE_NATIVE_ENDIAN);
     pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY,
                      intel_hda_map);
     if (d->msi) {
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 5ae21e910f..210956860c 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -242,7 +242,8 @@ static int ioapic_init1(SysBusDevice *dev)
     int io_memory;
 
     io_memory = cpu_register_io_memory(ioapic_mem_read,
-                                       ioapic_mem_write, s);
+                                       ioapic_mem_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, io_memory);
 
     qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 4e306de9cf..0cb1afbf2e 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -31,11 +31,13 @@ static ISABus *isabus;
 target_phys_addr_t isa_mem_base = 0;
 
 static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *isabus_get_fw_dev_path(DeviceState *dev);
 
 static struct BusInfo isa_bus_info = {
     .name      = "ISA",
     .size      = sizeof(ISABus),
     .print_dev = isabus_dev_print,
+    .get_fw_dev_path = isabus_get_fw_dev_path,
 };
 
 ISABus *isa_bus_new(DeviceState *dev)
@@ -68,12 +70,10 @@ void isa_bus_irqs(qemu_irq *irqs)
 qemu_irq isa_reserve_irq(int isairq)
 {
     if (isairq < 0 || isairq > 15) {
-        fprintf(stderr, "isa irq %d invalid\n", isairq);
-        exit(1);
+        hw_error("isa irq %d invalid", isairq);
     }
     if (isabus->assigned & (1 << isairq)) {
-        fprintf(stderr, "isa irq %d already assigned\n", isairq);
-        exit(1);
+        hw_error("isa irq %d already assigned", isairq);
     }
     isabus->assigned |= (1 << isairq);
     return isabus->irqs[isairq];
@@ -83,8 +83,7 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
 {
     assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
     if (isabus->assigned & (1 << isairq)) {
-        fprintf(stderr, "isa irq %d already assigned\n", isairq);
-        exit(1);
+        hw_error("isa irq %d already assigned", isairq);
     }
     isabus->assigned |= (1 << isairq);
     dev->isairq[dev->nirqs] = isairq;
@@ -92,6 +91,31 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
     dev->nirqs++;
 }
 
+static void isa_init_ioport_one(ISADevice *dev, uint16_t ioport)
+{
+    assert(dev->nioports < ARRAY_SIZE(dev->ioports));
+    dev->ioports[dev->nioports++] = ioport;
+}
+
+static int isa_cmp_ports(const void *p1, const void *p2)
+{
+    return *(uint16_t*)p1 - *(uint16_t*)p2;
+}
+
+void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length)
+{
+    int i;
+    for (i = start; i < start + length; i++) {
+        isa_init_ioport_one(dev, i);
+    }
+    qsort(dev->ioports, dev->nioports, sizeof(dev->ioports[0]), isa_cmp_ports);
+}
+
+void isa_init_ioport(ISADevice *dev, uint16_t ioport)
+{
+    isa_init_ioport_range(dev, ioport, 1);
+}
+
 static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     ISADevice *dev = DO_UPCAST(ISADevice, qdev, qdev);
@@ -115,7 +139,7 @@ ISADevice *isa_create(const char *name)
     DeviceState *dev;
 
     if (!isabus) {
-        hw_error("Tried to create isa device %s with no isa bus present.\n",
+        hw_error("Tried to create isa device %s with no isa bus present.",
                  name);
     }
     dev = qdev_create(&isabus->qbus, name);
@@ -153,6 +177,7 @@ static int isabus_bridge_init(SysBusDevice *dev)
 static SysBusDeviceInfo isabus_bridge_info = {
     .init = isabus_bridge_init,
     .qdev.name  = "isabus-bridge",
+    .qdev.fw_name  = "isa",
     .qdev.size  = sizeof(SysBusDevice),
     .qdev.no_user = 1,
 };
@@ -162,4 +187,18 @@ static void isabus_register_devices(void)
     sysbus_register_withprop(&isabus_bridge_info);
 }
 
+static char *isabus_get_fw_dev_path(DeviceState *dev)
+{
+    ISADevice *d = (ISADevice*)dev;
+    char path[40];
+    int off;
+
+    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
+    if (d->nioports) {
+        snprintf(path + off, sizeof(path) - off, "@%04x", d->ioports[0]);
+    }
+
+    return strdup(path);
+}
+
 device_init(isabus_register_devices)
diff --git a/hw/isa.h b/hw/isa.h
index aaf0272c25..19aa94c9fd 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -14,6 +14,8 @@ struct ISADevice {
     DeviceState qdev;
     uint32_t isairq[2];
     int nirqs;
+    uint16_t ioports[32];
+    int nioports;
 };
 
 typedef int (*isa_qdev_initfn)(ISADevice *dev);
@@ -26,13 +28,15 @@ ISABus *isa_bus_new(DeviceState *dev);
 void isa_bus_irqs(qemu_irq *irqs);
 qemu_irq isa_reserve_irq(int isairq);
 void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
+void isa_init_ioport(ISADevice *dev, uint16_t ioport);
+void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length);
 void isa_qdev_register(ISADeviceInfo *info);
 ISADevice *isa_create(const char *name);
 ISADevice *isa_create_simple(const char *name);
 
 extern target_phys_addr_t isa_mem_base;
 
-void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size, int be);
+void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size);
 
 /* dma.c */
 int DMA_get_channel_mode (int nchan);
diff --git a/hw/isa_mmio.c b/hw/isa_mmio.c
index 66bdd2cef6..ca957fb010 100644
--- a/hw/isa_mmio.c
+++ b/hw/isa_mmio.c
@@ -31,27 +31,13 @@ static void isa_mmio_writeb (void *opaque, target_phys_addr_t addr,
     cpu_outb(addr & IOPORTS_MASK, val);
 }
 
-static void isa_mmio_writew_be(void *opaque, target_phys_addr_t addr,
+static void isa_mmio_writew(void *opaque, target_phys_addr_t addr,
                                uint32_t val)
 {
-    val = bswap16(val);
     cpu_outw(addr & IOPORTS_MASK, val);
 }
 
-static void isa_mmio_writew_le(void *opaque, target_phys_addr_t addr,
-                               uint32_t val)
-{
-    cpu_outw(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writel_be(void *opaque, target_phys_addr_t addr,
-                               uint32_t val)
-{
-    val = bswap32(val);
-    cpu_outl(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writel_le(void *opaque, target_phys_addr_t addr,
+static void isa_mmio_writel(void *opaque, target_phys_addr_t addr,
                                uint32_t val)
 {
     cpu_outl(addr & IOPORTS_MASK, val);
@@ -59,84 +45,38 @@ static void isa_mmio_writel_le(void *opaque, target_phys_addr_t addr,
 
 static uint32_t isa_mmio_readb (void *opaque, target_phys_addr_t addr)
 {
-    uint32_t val;
-
-    val = cpu_inb(addr & IOPORTS_MASK);
-    return val;
+    return cpu_inb(addr & IOPORTS_MASK);
 }
 
-static uint32_t isa_mmio_readw_be(void *opaque, target_phys_addr_t addr)
+static uint32_t isa_mmio_readw(void *opaque, target_phys_addr_t addr)
 {
-    uint32_t val;
-
-    val = cpu_inw(addr & IOPORTS_MASK);
-    val = bswap16(val);
-    return val;
+    return cpu_inw(addr & IOPORTS_MASK);
 }
 
-static uint32_t isa_mmio_readw_le(void *opaque, target_phys_addr_t addr)
+static uint32_t isa_mmio_readl(void *opaque, target_phys_addr_t addr)
 {
-    uint32_t val;
-
-    val = cpu_inw(addr & IOPORTS_MASK);
-    return val;
+    return cpu_inl(addr & IOPORTS_MASK);
 }
 
-static uint32_t isa_mmio_readl_be(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-
-    val = cpu_inl(addr & IOPORTS_MASK);
-    val = bswap32(val);
-    return val;
-}
-
-static uint32_t isa_mmio_readl_le(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t val;
-
-    val = cpu_inl(addr & IOPORTS_MASK);
-    return val;
-}
-
-static CPUWriteMemoryFunc * const isa_mmio_write_be[] = {
-    &isa_mmio_writeb,
-    &isa_mmio_writew_be,
-    &isa_mmio_writel_be,
-};
-
-static CPUReadMemoryFunc * const isa_mmio_read_be[] = {
-    &isa_mmio_readb,
-    &isa_mmio_readw_be,
-    &isa_mmio_readl_be,
-};
-
-static CPUWriteMemoryFunc * const isa_mmio_write_le[] = {
+static CPUWriteMemoryFunc * const isa_mmio_write[] = {
     &isa_mmio_writeb,
-    &isa_mmio_writew_le,
-    &isa_mmio_writel_le,
+    &isa_mmio_writew,
+    &isa_mmio_writel,
 };
 
-static CPUReadMemoryFunc * const isa_mmio_read_le[] = {
+static CPUReadMemoryFunc * const isa_mmio_read[] = {
     &isa_mmio_readb,
-    &isa_mmio_readw_le,
-    &isa_mmio_readl_le,
+    &isa_mmio_readw,
+    &isa_mmio_readl,
 };
 
-static int isa_mmio_iomemtype = 0;
-
-void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size, int be)
+void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size)
 {
-    if (!isa_mmio_iomemtype) {
-        if (be) {
-            isa_mmio_iomemtype = cpu_register_io_memory(isa_mmio_read_be,
-                                                        isa_mmio_write_be,
-                                                        NULL);
-        } else {
-            isa_mmio_iomemtype = cpu_register_io_memory(isa_mmio_read_le,
-                                                        isa_mmio_write_le,
-                                                        NULL);
-        }
-    }
+    int isa_mmio_iomemtype;
+
+    isa_mmio_iomemtype = cpu_register_io_memory(isa_mmio_read,
+                                                isa_mmio_write,
+                                                NULL,
+                                                DEVICE_LITTLE_ENDIAN);
     cpu_register_physical_memory(base, size, isa_mmio_iomemtype);
 }
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 06dce70e78..7b19a81a47 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -720,7 +720,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
     s->shm_fd = 0;
 
     s->ivshmem_mmio_io_addr = cpu_register_io_memory(ivshmem_mmio_read,
-                                    ivshmem_mmio_write, s);
+                                    ivshmem_mmio_write, s, DEVICE_NATIVE_ENDIAN);
     /* region for registers*/
     pci_register_bar(&s->dev, 0, IVSHMEM_REG_BAR_SIZE,
                            PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_mmio_map);
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 4cb680c3e4..1dc22cf2e3 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -316,7 +316,8 @@ void jazz_led_init(target_phys_addr_t base)
 
     s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
 
-    io = cpu_register_io_memory(led_read, led_write, s);
+    io = cpu_register_io_memory(led_read, led_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 1, io);
 
     s->ds = graphic_console_init(jazz_led_update_display,
diff --git a/hw/lan9118.c b/hw/lan9118.c
index b996dc4f0c..a98866479b 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -1124,7 +1124,8 @@ static int lan9118_init1(SysBusDevice *dev)
     int i;
 
     s->mmio_index = cpu_register_io_memory(lan9118_readfn,
-                                           lan9118_writefn, s);
+                                           lan9118_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x100, s->mmio_index);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/lance.c b/hw/lance.c
index dc12144ded..ddb1cbb7a4 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -118,7 +118,8 @@ static int lance_init(SysBusDevice *dev)
     PCNetState *s = &d->state;
 
     s->mmio_index =
-        cpu_register_io_memory(lance_mem_read, lance_mem_write, d);
+        cpu_register_io_memory(lance_mem_read, lance_mem_write, d,
+                               DEVICE_NATIVE_ENDIAN);
 
     qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
 
@@ -141,6 +142,7 @@ static void lance_reset(DeviceState *dev)
 static SysBusDeviceInfo lance_info = {
     .init       = lance_init,
     .qdev.name  = "lance",
+    .qdev.fw_name  = "ethernet",
     .qdev.size  = sizeof(SysBusPCNetState),
     .qdev.reset = lance_reset,
     .qdev.vmsd  = &vmstate_lance,
diff --git a/hw/loader.c b/hw/loader.c
index 49ac1fa1cc..eb198f6723 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -107,7 +107,7 @@ int load_image_targphys(const char *filename,
 
     size = get_image_size(filename);
     if (size > 0)
-        rom_add_file_fixed(filename, addr);
+        rom_add_file_fixed(filename, addr, -1);
     return size;
 }
 
@@ -557,10 +557,11 @@ static void rom_insert(Rom *rom)
 }
 
 int rom_add_file(const char *file, const char *fw_dir,
-                 target_phys_addr_t addr)
+                 target_phys_addr_t addr, int32_t bootindex)
 {
     Rom *rom;
     int rc, fd = -1;
+    char devpath[100];
 
     rom = qemu_mallocz(sizeof(*rom));
     rom->name = qemu_strdup(file);
@@ -592,8 +593,25 @@ int rom_add_file(const char *file, const char *fw_dir,
     }
     close(fd);
     rom_insert(rom);
-    if (rom->fw_file && fw_cfg)
-        fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize);
+    if (rom->fw_file && fw_cfg) {
+        const char *basename;
+        char fw_file_name[56];
+
+        basename = strrchr(rom->fw_file, '/');
+        if (basename) {
+            basename++;
+        } else {
+            basename = rom->fw_file;
+        }
+        snprintf(fw_file_name, sizeof(fw_file_name), "%s/%s", rom->fw_dir,
+                 basename);
+        fw_cfg_add_file(fw_cfg, fw_file_name, rom->data, rom->romsize);
+        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
+    } else {
+        snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
+    }
+
+    add_boot_device_path(bootindex, NULL, devpath);
     return 0;
 
 err:
@@ -623,12 +641,12 @@ int rom_add_blob(const char *name, const void *blob, size_t len,
 
 int rom_add_vga(const char *file)
 {
-    return rom_add_file(file, "vgaroms", 0);
+    return rom_add_file(file, "vgaroms", 0, -1);
 }
 
-int rom_add_option(const char *file)
+int rom_add_option(const char *file, int32_t bootindex)
 {
-    return rom_add_file(file, "genroms", 0);
+    return rom_add_file(file, "genroms", 0, bootindex);
 }
 
 static void rom_reset(void *unused)
diff --git a/hw/loader.h b/hw/loader.h
index 1f82fc5e98..fc6bdff6bb 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -22,7 +22,7 @@ void pstrcpy_targphys(const char *name,
 
 
 int rom_add_file(const char *file, const char *fw_dir,
-                 target_phys_addr_t addr);
+                 target_phys_addr_t addr, int32_t bootindex);
 int rom_add_blob(const char *name, const void *blob, size_t len,
                  target_phys_addr_t addr);
 int rom_load_all(void);
@@ -31,8 +31,8 @@ int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size);
 void *rom_ptr(target_phys_addr_t addr);
 void do_info_roms(Monitor *mon);
 
-#define rom_add_file_fixed(_f, _a)              \
-    rom_add_file(_f, NULL, _a)
+#define rom_add_file_fixed(_f, _a, _i)          \
+    rom_add_file(_f, NULL, _a, _i)
 #define rom_add_blob_fixed(_f, _b, _l, _a)      \
     rom_add_blob(_f, _b, _l, _a)
 
@@ -43,6 +43,6 @@ void do_info_roms(Monitor *mon);
 #define PC_ROM_SIZE        (PC_ROM_MAX - PC_ROM_MIN_VGA)
 
 int rom_add_vga(const char *file);
-int rom_add_option(const char *file);
+int rom_add_option(const char *file, int32_t bootindex);
 
 #endif
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 1aef62f9a6..0129ae3cc0 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2173,9 +2173,11 @@ static int lsi_scsi_init(PCIDevice *dev)
     pci_conf[PCI_INTERRUPT_PIN] = 0x01;
 
     s->mmio_io_addr = cpu_register_io_memory(lsi_mmio_readfn,
-                                             lsi_mmio_writefn, s);
+                                             lsi_mmio_writefn, s,
+                                             DEVICE_NATIVE_ENDIAN);
     s->ram_io_addr = cpu_register_io_memory(lsi_ram_readfn,
-                                            lsi_ram_writefn, s);
+                                            lsi_ram_writefn, s,
+                                            DEVICE_NATIVE_ENDIAN);
 
     pci_register_bar(&s->dev, 0, 256,
                            PCI_BASE_ADDRESS_SPACE_IO, lsi_io_mapfunc);
diff --git a/hw/m48t59.c b/hw/m48t59.c
index c7492a65fe..6991e2e8e1 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -680,6 +680,7 @@ M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type)
     if (io_base != 0) {
         register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
         register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
+        isa_init_ioport_range(dev, io_base, 4);
     }
 
     return s;
@@ -716,7 +717,8 @@ static int m48t59_init1(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->IRQ);
 
-    mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
+    mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, s->size, mem_index);
     m48t59_init_common(s);
 
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 03d2d16d29..5680fa9c1c 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -707,8 +707,6 @@ static void dbdma_writel (void *opaque,
     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
 
-    value = bswap32(value);
-
     /* cmdptr cannot be modified if channel is RUN or ACTIVE */
 
     if (reg == DBDMA_CMDPTR_LO &&
@@ -788,7 +786,6 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
         break;
     }
 
-    value = bswap32(value);
     return value;
 }
 
@@ -844,7 +841,8 @@ void* DBDMA_init (int *dbdma_mem_index)
 
     s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
 
-    *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s);
+    *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
+                                              DEVICE_LITTLE_ENDIAN);
     register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
     qemu_register_reset(dbdma_reset, s);
 
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index ce287c31de..c2a2fc21e4 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -138,7 +138,8 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
     s->size = size;
     s->it_shift = it_shift;
 
-    s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s);
+    s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
+                                          DEVICE_NATIVE_ENDIAN);
     *mem_index = s->mem_index;
     register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
                     macio_nvram_load, s);
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 307b584718..3eff925b0e 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -249,7 +249,8 @@ static int mv88w8618_audio_init(SysBusDevice *dev)
     wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
 
     iomemtype = cpu_register_io_memory(mv88w8618_audio_readfn,
-                                       mv88w8618_audio_writefn, s);
+                                       mv88w8618_audio_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype);
 
     return 0;
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 2b91fa839e..6466aff316 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -605,6 +605,7 @@ static int rtc_initfn(ISADevice *dev)
 
     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
     register_ioport_read(base, 2, 1, cmos_ioport_read, s);
+    isa_init_ioport_range(dev, base, 2);
 
     qdev_set_legacy_instance_id(&dev->qdev, base, 2);
     qemu_register_reset(rtc_reset, s);
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index c107de8c61..2a618d4446 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -525,7 +525,8 @@ qemu_irq *mcf5206_init(uint32_t base, CPUState *env)
 
     s = (m5206_mbar_state *)qemu_mallocz(sizeof(m5206_mbar_state));
     iomemtype = cpu_register_io_memory(m5206_mbar_readfn,
-                                       m5206_mbar_writefn, s);
+                                       m5206_mbar_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
     pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 38645f7285..17a692d4a3 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -179,7 +179,8 @@ static void mcf5208_sys_init(qemu_irq *pic)
     int i;
 
     iomemtype = cpu_register_io_memory(m5208_sys_readfn,
-                                       m5208_sys_writefn, NULL);
+                                       m5208_sys_writefn, NULL,
+                                       DEVICE_NATIVE_ENDIAN);
     /* SDRAMC.  */
     cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
     /* Timers.  */
@@ -188,7 +189,8 @@ static void mcf5208_sys_init(qemu_irq *pic)
         bh = qemu_bh_new(m5208_timer_trigger, s);
         s->timer = ptimer_init(bh);
         iomemtype = cpu_register_io_memory(m5208_timer_readfn,
-                                           m5208_timer_writefn, s);
+                                           m5208_timer_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
         cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
                                      iomemtype);
         s->irq = pic[4 + i];
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 4e7fbed160..21035da345 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -467,7 +467,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
     s->irq = irq;
     s->mmio_index = cpu_register_io_memory(mcf_fec_readfn,
-                                           mcf_fec_writefn, s);
+                                           mcf_fec_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x400, s->mmio_index);
 
     memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index f01bd320a4..ac04295198 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -149,7 +149,8 @@ qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
     mcf_intc_reset(s);
 
     iomemtype = cpu_register_io_memory(mcf_intc_readfn,
-                                       mcf_intc_writefn, s);
+                                       mcf_intc_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index d16bac7337..db57096af2 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -304,6 +304,7 @@ void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
 
     s = mcf_uart_init(irq, chr);
     iomemtype = cpu_register_io_memory(mcf_uart_readfn,
-                                       mcf_uart_writefn, s);
+                                       mcf_uart_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x40, iomemtype);
 }
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 66397c0c9a..a7caa3f171 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -191,7 +191,8 @@ void mips_jazz_init (ram_addr_t ram_size,
 
     /* Chipset */
     rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas);
-    s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
+    s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
 
     /* ISA devices */
@@ -204,12 +205,7 @@ void mips_jazz_init (ram_addr_t ram_size,
     pcspk_init(pit);
 
     /* ISA IO space at 0x90000000 */
-#ifdef TARGET_WORDS_BIGENDIAN
-    isa_mmio_init(0x90000000, 0x01000000, 1);
-#else
-    isa_mmio_init(0x90000000, 0x01000000, 0);
-#endif
-
+    isa_mmio_init(0x90000000, 0x01000000);
     isa_mem_base = 0x11000000;
 
     /* Video card */
@@ -259,7 +255,8 @@ void mips_jazz_init (ram_addr_t ram_size,
 
     /* Real time clock */
     rtc_init(1980, NULL);
-    s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
+    s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL,
+                                   DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
 
     /* Keyboard (i8042) */
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 6be8aa70f9..5ef3fcbea9 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -436,7 +436,8 @@ static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_ir
     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
 
     malta = cpu_register_io_memory(malta_fpga_read,
-                                   malta_fpga_write, s);
+                                   malta_fpga_write, s,
+                                   DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x900, malta);
     /* 0xa00 is less than a page, so will still get the right offsets.  */
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 111c7592ea..380a7eb78c 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -186,11 +186,7 @@ mips_mipssim_init (ram_addr_t ram_size,
     cpu_mips_clock_init(env);
 
     /* Register 64 KB of ISA IO space at 0x1fd00000. */
-#ifdef TARGET_WORDS_BIGENDIAN
-    isa_mmio_init(0x1fd00000, 0x00010000, 1);
-#else
-    isa_mmio_init(0x1fd00000, 0x00010000, 0);
-#endif
+    isa_mmio_init(0x1fd00000, 0x00010000);
 
     /* A single 16450 sits at offset 0x3f8. It is attached to
        MIPS CPU INT2, which is interrupt 4. */
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index aa348904ad..fb34dcfcdc 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -204,7 +204,8 @@ void mips_r4k_init (ram_addr_t ram_size,
 
     if (!mips_qemu_iomemtype) {
         mips_qemu_iomemtype = cpu_register_io_memory(mips_qemu_read,
-                                                     mips_qemu_write, NULL);
+                                                     mips_qemu_write, NULL,
+                                                     DEVICE_NATIVE_ENDIAN);
     }
     cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);
 
@@ -270,11 +271,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     rtc_init(2000, NULL);
 
     /* Register 64 KB of ISA IO space at 0x14000000 */
-#ifdef TARGET_WORDS_BIGENDIAN
-    isa_mmio_init(0x14000000, 0x00010000, 1);
-#else
-    isa_mmio_init(0x14000000, 0x00010000, 0);
-#endif
+    isa_mmio_init(0x14000000, 0x00010000);
     isa_mem_base = 0x10000000;
 
     pit = pit_init(0x40, i8259[0]);
diff --git a/hw/mpcore.c b/hw/mpcore.c
index b4db1914b7..fc0521549a 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -276,7 +276,8 @@ static int mpcore_priv_init(SysBusDevice *dev)
 
     gic_init(&s->gic, s->num_cpu);
     s->iomemtype = cpu_register_io_memory(mpcore_priv_readfn,
-                                          mpcore_priv_writefn, s);
+                                          mpcore_priv_writefn, s,
+                                          DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map);
     for (i = 0; i < s->num_cpu * 2; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
diff --git a/hw/msix.c b/hw/msix.c
index f66d2550a7..e1230824b2 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -254,7 +254,8 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
     msix_mask_all(dev, nentries);
 
     dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read,
-                                                  msix_mmio_write, dev);
+                                                  msix_mmio_write, dev,
+                                                  DEVICE_NATIVE_ENDIAN);
     if (dev->msix_mmio_index == -1) {
         ret = -EBUSY;
         goto err_index;
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 8fc348f75b..5252fc5e1c 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -232,7 +232,7 @@ qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
 	s->pins = qi;
 
 	iomemtype = cpu_register_io_memory(mst_fpga_readfn,
-		mst_fpga_writefn, s);
+		mst_fpga_writefn, s, DEVICE_NATIVE_ENDIAN);
 	cpu_register_physical_memory(base, 0x00100000, iomemtype);
 	register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
                         mst_fpga_load, s);
diff --git a/hw/multiboot.c b/hw/multiboot.c
index e710bbb948..7cc3055359 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -331,7 +331,8 @@ int load_multiboot(void *fw_cfg,
     fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, mb_bootinfo_data,
                      sizeof(bootinfo));
 
-    option_rom[nb_option_roms] = "multiboot.bin";
+    option_rom[nb_option_roms].name = "multiboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
     nb_option_roms++;
 
     return 1; /* yes, we are multiboot */
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 56f27669d2..d98aa8d03c 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -388,7 +388,8 @@ static int mv88w8618_eth_init(SysBusDevice *dev)
     s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
                           dev->qdev.info->name, dev->qdev.id, s);
     s->mmio_index = cpu_register_io_memory(mv88w8618_eth_readfn,
-                                           mv88w8618_eth_writefn, s);
+                                           mv88w8618_eth_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_ETH_SIZE, s->mmio_index);
     return 0;
 }
@@ -600,7 +601,8 @@ static int musicpal_lcd_init(SysBusDevice *dev)
     s->brightness = 7;
 
     iomemtype = cpu_register_io_memory(musicpal_lcd_readfn,
-                                       musicpal_lcd_writefn, s);
+                                       musicpal_lcd_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_LCD_SIZE, iomemtype);
 
     s->ds = graphic_console_init(lcd_refresh, lcd_invalidate,
@@ -725,7 +727,8 @@ static int mv88w8618_pic_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
     sysbus_init_irq(dev, &s->parent_irq);
     iomemtype = cpu_register_io_memory(mv88w8618_pic_readfn,
-                                       mv88w8618_pic_writefn, s);
+                                       mv88w8618_pic_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_PIC_SIZE, iomemtype);
     return 0;
 }
@@ -886,7 +889,8 @@ static int mv88w8618_pit_init(SysBusDevice *dev)
     }
 
     iomemtype = cpu_register_io_memory(mv88w8618_pit_readfn,
-                                       mv88w8618_pit_writefn, s);
+                                       mv88w8618_pit_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_PIT_SIZE, iomemtype);
     return 0;
 }
@@ -976,7 +980,8 @@ static int mv88w8618_flashcfg_init(SysBusDevice *dev)
 
     s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
     iomemtype = cpu_register_io_memory(mv88w8618_flashcfg_readfn,
-                                       mv88w8618_flashcfg_writefn, s);
+                                       mv88w8618_flashcfg_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_FLASHCFG_SIZE, iomemtype);
     return 0;
 }
@@ -1037,7 +1042,8 @@ static void musicpal_misc_init(void)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(musicpal_misc_readfn,
-                                       musicpal_misc_writefn, NULL);
+                                       musicpal_misc_writefn, NULL,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(MP_MISC_BASE, MP_MISC_SIZE, iomemtype);
 }
 
@@ -1082,7 +1088,8 @@ static int mv88w8618_wlan_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(mv88w8618_wlan_readfn,
-                                       mv88w8618_wlan_writefn, NULL);
+                                       mv88w8618_wlan_writefn, NULL,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_WLAN_SIZE, iomemtype);
     return 0;
 }
@@ -1293,7 +1300,8 @@ static int musicpal_gpio_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     iomemtype = cpu_register_io_memory(musicpal_gpio_readfn,
-                                       musicpal_gpio_writefn, s);
+                                       musicpal_gpio_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MP_GPIO_SIZE, iomemtype);
 
     qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c
index 03a5a1fbd5..3ff0d89a74 100644
--- a/hw/ne2000-isa.c
+++ b/hw/ne2000-isa.c
@@ -68,14 +68,17 @@ static int isa_ne2000_initfn(ISADevice *dev)
 
     register_ioport_write(isa->iobase, 16, 1, ne2000_ioport_write, s);
     register_ioport_read(isa->iobase, 16, 1, ne2000_ioport_read, s);
+    isa_init_ioport_range(dev, isa->iobase, 16);
 
     register_ioport_write(isa->iobase + 0x10, 1, 1, ne2000_asic_ioport_write, s);
     register_ioport_read(isa->iobase + 0x10, 1, 1, ne2000_asic_ioport_read, s);
     register_ioport_write(isa->iobase + 0x10, 2, 2, ne2000_asic_ioport_write, s);
     register_ioport_read(isa->iobase + 0x10, 2, 2, ne2000_asic_ioport_read, s);
+    isa_init_ioport_range(dev, isa->iobase + 0x10, 2);
 
     register_ioport_write(isa->iobase + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
     register_ioport_read(isa->iobase + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
+    isa_init_ioport(dev, isa->iobase + 0x1f);
 
     isa_init_irq(dev, &s->irq, isa->isairq);
 
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 126e7cfeaf..5966359852 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -26,6 +26,7 @@
 #include "net.h"
 #include "ne2000.h"
 #include "loader.h"
+#include "sysemu.h"
 
 /* debug NE2000 card */
 //#define DEBUG_NE2000
@@ -741,11 +742,13 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
     if (!pci_dev->qdev.hotplugged) {
         static int loaded = 0;
         if (!loaded) {
-            rom_add_option("pxe-ne2k_pci.bin");
+            rom_add_option("pxe-ne2k_pci.bin", -1);
             loaded = 1;
         }
     }
 
+    add_boot_device_path(s->c.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+
     return 0;
 }
 
diff --git a/hw/nseries.c b/hw/nseries.c
index 04a028dc27..2f6f473d64 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1326,7 +1326,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
         qemu_register_reset(n8x0_boot_init, s);
     }
 
-    if (option_rom[0] && (boot_device[0] == 'n' || !kernel_filename)) {
+    if (option_rom[0].name && (boot_device[0] == 'n' || !kernel_filename)) {
         int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
@@ -1341,7 +1341,7 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
          *
          * The code above is for loading the `zImage' file from Nokia
          * images.  */
-        rom_size = load_image_targphys(option_rom[0],
+        rom_size = load_image_targphys(option_rom[0].name,
                                        OMAP2_Q2_BASE + 0x400000,
                                        sdram_size - 0x400000);
         printf("%i bytes of image loaded\n", rom_size);
diff --git a/hw/omap.h b/hw/omap.h
index fe32ca5c4c..c227a82b2c 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -1129,7 +1129,8 @@ inline static int debug_register_io_memory(CPUReadMemoryFunc * const *mem_read,
     s->mem_write = mem_write;
     s->opaque = opaque;
     s->in = 0;
-    return cpu_register_io_memory(io_readfn, io_writefn, s);
+    return cpu_register_io_memory(io_readfn, io_writefn, s,
+                                  DEVICE_NATIVE_ENDIAN);
 }
 #  define cpu_register_io_memory	debug_register_io_memory
 # endif
diff --git a/hw/omap1.c b/hw/omap1.c
index f4966f74b6..d5e4dabc87 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -264,7 +264,7 @@ static struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
     omap_timer_clk_setup(s);
 
     iomemtype = cpu_register_io_memory(omap_mpu_timer_readfn,
-                    omap_mpu_timer_writefn, s);
+                    omap_mpu_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
@@ -387,7 +387,7 @@ static struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
     omap_timer_clk_setup(&s->timer);
 
     iomemtype = cpu_register_io_memory(omap_wd_timer_readfn,
-                    omap_wd_timer_writefn, s);
+                    omap_wd_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
@@ -489,7 +489,7 @@ static struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
     omap_timer_clk_setup(&s->timer);
 
     iomemtype = cpu_register_io_memory(omap_os_timer_readfn,
-                    omap_os_timer_writefn, s);
+                    omap_os_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
@@ -716,7 +716,7 @@ static void omap_ulpd_pm_init(target_phys_addr_t base,
                 struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_ulpd_pm_readfn,
-                    omap_ulpd_pm_writefn, mpu);
+                    omap_ulpd_pm_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x800, iomemtype);
     omap_ulpd_pm_reset(mpu);
@@ -931,7 +931,7 @@ static void omap_pin_cfg_init(target_phys_addr_t base,
                 struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_pin_cfg_readfn,
-                    omap_pin_cfg_writefn, mpu);
+                    omap_pin_cfg_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x800, iomemtype);
     omap_pin_cfg_reset(mpu);
@@ -1001,7 +1001,7 @@ static CPUWriteMemoryFunc * const omap_id_writefn[] = {
 static void omap_id_init(struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_id_readfn,
-                    omap_id_writefn, mpu);
+                    omap_id_writefn, mpu, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory_offset(0xfffe1800, 0x800, iomemtype, 0xfffe1800);
     cpu_register_physical_memory_offset(0xfffed400, 0x100, iomemtype, 0xfffed400);
     if (!cpu_is_omap15xx(mpu))
@@ -1084,7 +1084,7 @@ static void omap_mpui_init(target_phys_addr_t base,
                 struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_mpui_readfn,
-                    omap_mpui_writefn, mpu);
+                    omap_mpui_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
@@ -1193,7 +1193,7 @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
     omap_tipb_bridge_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_tipb_bridge_readfn,
-                    omap_tipb_bridge_writefn, s);
+                    omap_tipb_bridge_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
     return s;
@@ -1299,7 +1299,7 @@ static void omap_tcmi_init(target_phys_addr_t base,
                 struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_tcmi_readfn,
-                    omap_tcmi_writefn, mpu);
+                    omap_tcmi_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 
     cpu_register_physical_memory(base, 0x100, iomemtype);
     omap_tcmi_reset(mpu);
@@ -1372,7 +1372,7 @@ static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
                 omap_clk clk)
 {
     int iomemtype = cpu_register_io_memory(omap_dpll_readfn,
-                    omap_dpll_writefn, s);
+                    omap_dpll_writefn, s, DEVICE_NATIVE_ENDIAN);
 
     s->dpll = clk;
     omap_dpll_reset(s);
@@ -1776,8 +1776,10 @@ static void omap_clkm_init(target_phys_addr_t mpu_base,
                 target_phys_addr_t dsp_base, struct omap_mpu_state_s *s)
 {
     int iomemtype[2] = {
-        cpu_register_io_memory(omap_clkm_readfn, omap_clkm_writefn, s),
-        cpu_register_io_memory(omap_clkdsp_readfn, omap_clkdsp_writefn, s),
+        cpu_register_io_memory(omap_clkm_readfn, omap_clkm_writefn, s,
+                               DEVICE_NATIVE_ENDIAN),
+        cpu_register_io_memory(omap_clkdsp_readfn, omap_clkdsp_writefn, s,
+                               DEVICE_NATIVE_ENDIAN),
     };
 
     s->clkm.arm_idlect1 = 0x03ff;
@@ -2031,7 +2033,7 @@ struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
     omap_mpuio_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_mpuio_readfn,
-                    omap_mpuio_writefn, s);
+                    omap_mpuio_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
@@ -2216,7 +2218,7 @@ struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
     omap_uwire_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_uwire_readfn,
-                    omap_uwire_writefn, s);
+                    omap_uwire_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
@@ -2317,7 +2319,7 @@ static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
     omap_pwl_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_pwl_readfn,
-                    omap_pwl_writefn, s);
+                    omap_pwl_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
@@ -2412,7 +2414,7 @@ static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
     omap_pwt_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_pwt_readfn,
-                    omap_pwt_writefn, s);
+                    omap_pwt_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 }
 
@@ -2825,7 +2827,7 @@ static struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
     omap_rtc_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_rtc_readfn,
-                    omap_rtc_writefn, s);
+                    omap_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
@@ -3347,7 +3349,7 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
     omap_mcbsp_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_mcbsp_readfn,
-                    omap_mcbsp_writefn, s);
+                    omap_mcbsp_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
@@ -3519,7 +3521,7 @@ static struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
     omap_lpg_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_lpg_readfn,
-                    omap_lpg_writefn, s);
+                    omap_lpg_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
@@ -3552,7 +3554,7 @@ static CPUWriteMemoryFunc * const omap_mpui_io_writefn[] = {
 static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
 {
     int iomemtype = cpu_register_io_memory(omap_mpui_io_readfn,
-                    omap_mpui_io_writefn, mpu);
+                    omap_mpui_io_writefn, mpu, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_MPUI_BASE, 0x7fff, iomemtype);
 }
 
diff --git a/hw/omap2.c b/hw/omap2.c
index e35a56e043..0f13272c7b 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -600,7 +600,7 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
     AUD_register_card("OMAP EAC", &s->codec.card);
 
     iomemtype = cpu_register_io_memory(omap_eac_readfn,
-                    omap_eac_writefn, s);
+                    omap_eac_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype);
 
     return s;
@@ -788,7 +788,7 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
     omap_l4_attach(ta, 0, iomemtype);
 
     iomemtype = cpu_register_io_memory(omap_sti_fifo_readfn,
-                    omap_sti_fifo_writefn, s);
+                    omap_sti_fifo_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(channel_base, 0x10000, iomemtype);
 
     return s;
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index 3e718ba7f1..8e2dcc90c8 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -1659,7 +1659,7 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_clk_update(s, 0, 1);
 
     iomemtype = cpu_register_io_memory(omap_dma_readfn,
-                    omap_dma_writefn, s);
+                    omap_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, memsize, iomemtype);
 
     mpu->drq = s->dma->drq;
@@ -2066,7 +2066,7 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_clk_update(s, 0, !!s->dma->freq);
 
     iomemtype = cpu_register_io_memory(omap_dma4_readfn,
-                    omap_dma4_writefn, s);
+                    omap_dma4_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     mpu->drq = s->dma->drq;
diff --git a/hw/omap_dss.c b/hw/omap_dss.c
index 044f2d2428..afe287a43e 100644
--- a/hw/omap_dss.c
+++ b/hw/omap_dss.c
@@ -1045,7 +1045,7 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta,
     iomemtype[3] = l4_register_io_memory(omap_venc1_readfn,
                     omap_venc1_writefn, s);
     iomemtype[4] = cpu_register_io_memory(omap_im3_readfn,
-                    omap_im3_writefn, s);
+                    omap_im3_writefn, s, DEVICE_NATIVE_ENDIAN);
     omap_l4_attach(ta, 0, iomemtype[0]);
     omap_l4_attach(ta, 1, iomemtype[1]);
     omap_l4_attach(ta, 2, iomemtype[2]);
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index d978c7abfd..478f7d9825 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -183,7 +183,7 @@ struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
     omap_gpio_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_gpio_readfn,
-                    omap_gpio_writefn, s);
+                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     return s;
diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
index 72cfeccf6f..8bf3343a61 100644
--- a/hw/omap_gpmc.c
+++ b/hw/omap_gpmc.c
@@ -390,7 +390,7 @@ struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
     omap_gpmc_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_gpmc_readfn,
-                    omap_gpmc_writefn, s);
+                    omap_gpmc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     return s;
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index d133977e7f..5cabb5a7b3 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -437,7 +437,7 @@ struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
     omap_i2c_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_i2c_readfn,
-                    omap_i2c_writefn, s);
+                    omap_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     return s;
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 59893b7add..001e20b9d3 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -371,7 +371,7 @@ struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base,
     omap_inth_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_inth_readfn,
-                    omap_inth_writefn, s);
+                    omap_inth_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, size, iomemtype);
 
     return s;
@@ -591,7 +591,7 @@ struct omap_intr_handler_s *omap2_inth_init(target_phys_addr_t base,
     omap_inth_reset(s);
 
     iomemtype = cpu_register_io_memory(omap2_inth_readfn,
-                    omap2_inth_writefn, s);
+                    omap2_inth_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, size, iomemtype);
 
     return s;
diff --git a/hw/omap_l4.c b/hw/omap_l4.c
index bf8ba36e99..4af0ca8ea6 100644
--- a/hw/omap_l4.c
+++ b/hw/omap_l4.c
@@ -107,7 +107,8 @@ int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                           CPUWriteMemoryFunc * const *mem_write,
                           void *opaque)
 {
-    return cpu_register_io_memory(mem_read, mem_write, opaque);
+    return cpu_register_io_memory(mem_read, mem_write, opaque,
+                                  DEVICE_NATIVE_ENDIAN);
 }
 #endif
 
@@ -131,7 +132,7 @@ struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
 
     omap_cpu_io_entry =
             cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus);
+                            omap_l4_io_writefn, bus, DEVICE_NATIVE_ENDIAN);
 # define L4_PAGES	(0xb4000 / TARGET_PAGE_SIZE)
     omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
     omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index 6affef67b9..0c2c55012b 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -450,7 +450,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
     omap_lcdc_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_lcdc_readfn,
-                    omap_lcdc_writefn, s);
+                    omap_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100, iomemtype);
 
     s->state = graphic_console_init(omap_update_display,
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index 9d167ff535..e9ec2f398b 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -587,7 +587,7 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
     omap_mmc_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_mmc_readfn,
-                    omap_mmc_writefn, s);
+                    omap_mmc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x800, iomemtype);
 
     /* Instantiate the storage */
diff --git a/hw/omap_sdrc.c b/hw/omap_sdrc.c
index aefaebe046..e18376260e 100644
--- a/hw/omap_sdrc.c
+++ b/hw/omap_sdrc.c
@@ -158,7 +158,7 @@ struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
     omap_sdrc_reset(s);
 
     iomemtype = cpu_register_io_memory(omap_sdrc_readfn,
-                    omap_sdrc_writefn, s);
+                    omap_sdrc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     return s;
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 44dc514f3f..06bccbdc4e 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -143,12 +143,15 @@ static void sx1_init(ram_addr_t ram_size,
                                  qemu_ram_alloc(NULL, "omap_sx1.flash0-0",
                                                 flash_size) | IO_MEM_ROM);
 
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
                     OMAP_CS0_SIZE - flash_size, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io);
 
     fl_idx = 0;
@@ -175,7 +178,8 @@ static void sx1_init(ram_addr_t ram_size,
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
                                      qemu_ram_alloc(NULL, "omap_sx1.flash1-0",
                                                     flash1_size) | IO_MEM_ROM);
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
+        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
+                                    DEVICE_NATIVE_ENDIAN);
         cpu_register_physical_memory(OMAP_CS1_BASE + flash1_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
@@ -189,7 +193,8 @@ static void sx1_init(ram_addr_t ram_size,
         }
         fl_idx++;
     } else {
-        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
+        io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
+                                    DEVICE_NATIVE_ENDIAN);
         cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io);
     }
 
diff --git a/hw/omap_uart.c b/hw/omap_uart.c
index cc66cd9d94..9cee81d7c9 100644
--- a/hw/omap_uart.c
+++ b/hw/omap_uart.c
@@ -170,7 +170,7 @@ struct omap_uart_s *omap2_uart_init(struct omap_target_agent_s *ta,
     struct omap_uart_s *s = omap_uart_init(base, irq,
                     fclk, iclk, txdma, rxdma, label, chr);
     int iomemtype = cpu_register_io_memory(omap_uart_readfn,
-                    omap_uart_writefn, s);
+                    omap_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
 
     s->ta = ta;
 
diff --git a/hw/onenand.c b/hw/onenand.c
index f7afecaaab..d9cdcf2944 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -630,7 +630,7 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
     s->blockwp = qemu_malloc(s->blocks);
     s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
-                    onenand_writefn, s);
+                    onenand_writefn, s, DEVICE_NATIVE_ENDIAN);
     if (!dinfo)
         s->image = memset(qemu_malloc(size + (size >> 5)),
                         0xff, size + (size >> 5));
diff --git a/hw/openpic.c b/hw/openpic.c
index f6b8f21272..6d2cf994ba 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -242,19 +242,10 @@ typedef struct openpic_t {
     int max_irq;
     int irq_ipi0;
     int irq_tim0;
-    int need_swap;
     void (*reset) (void *);
     void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
 } openpic_t;
 
-static inline uint32_t openpic_swap32(openpic_t *opp, uint32_t val)
-{
-    if (opp->need_swap)
-        return bswap32(val);
-
-    return val;
-}
-
 static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
 {
     set_bit(q->queue, n_IRQ);
@@ -599,7 +590,6 @@ static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t v
     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    val = openpic_swap32(opp, val);
     addr &= 0xFF;
     switch (addr) {
     case 0x00: /* FREP */
@@ -693,7 +683,6 @@ static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
         break;
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
-    retval = openpic_swap32(opp, retval);
 
     return retval;
 }
@@ -706,7 +695,6 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    val = openpic_swap32(opp, val);
     addr -= 0x1100;
     addr &= 0xFFFF;
     idx = (addr & 0xFFF0) >> 6;
@@ -759,7 +747,6 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
         break;
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
-    retval = openpic_swap32(opp, retval);
 
     return retval;
 }
@@ -772,7 +759,6 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
     DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    val = openpic_swap32(opp, val);
     addr = addr & 0xFFF0;
     idx = addr >> 5;
     if (addr & 0x10) {
@@ -804,7 +790,6 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr)
         retval = read_IRQreg(opp, idx, IRQ_IPVP);
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
-    retval = openpic_swap32(opp, retval);
 
     return retval;
 }
@@ -819,7 +804,6 @@ static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t v
     DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
     if (addr & 0xF)
         return;
-    val = openpic_swap32(opp, val);
     addr &= 0x1FFF0;
     idx = addr / 0x1000;
     dst = &opp->dst[idx];
@@ -937,7 +921,6 @@ static uint32_t openpic_cpu_read (void *opaque, target_phys_addr_t addr)
         break;
     }
     DPRINTF("%s: => %08x\n", __func__, retval);
-    retval = openpic_swap32(opp, retval);
 
     return retval;
 }
@@ -1035,7 +1018,8 @@ static void openpic_map(PCIDevice *pci_dev, int region_num,
     cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
 #if 0 // Don't implement ISU for now
     opp_io_memory = cpu_register_io_memory(openpic_src_read,
-                                           openpic_src_write);
+                                           openpic_src_write, NULL
+                                           DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
                                  opp_io_memory);
 #endif
@@ -1202,8 +1186,8 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     } else {
         opp = qemu_mallocz(sizeof(openpic_t));
     }
-    opp->mem_index = cpu_register_io_memory(openpic_read,
-                                            openpic_write, opp);
+    opp->mem_index = cpu_register_io_memory(openpic_read, openpic_write, opp,
+                                            DEVICE_LITTLE_ENDIAN);
 
     //    isu_base &= 0xFFFC0000;
     opp->nb_cpus = nb_cpus;
@@ -1231,7 +1215,6 @@ qemu_irq *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus,
     for (i = 0; i < nb_cpus; i++)
         opp->dst[i].irqs = irqs[i];
     opp->irq_out = irq_out;
-    opp->need_swap = 1;
 
     register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
                     openpic_save, openpic_load, opp);
@@ -1671,7 +1654,8 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
         int mem_index;
 
-        mem_index = cpu_register_io_memory(list[i].read, list[i].write, mpp);
+        mem_index = cpu_register_io_memory(list[i].read, list[i].write, mpp,
+                                           DEVICE_BIG_ENDIAN);
         if (mem_index < 0) {
             goto free;
         }
@@ -1687,7 +1671,6 @@ qemu_irq *mpic_init (target_phys_addr_t base, int nb_cpus,
     for (i = 0; i < nb_cpus; i++)
         mpp->dst[i].irqs = irqs[i];
     mpp->irq_out = irq_out;
-    mpp->need_swap = 0;    /* MPIC has the same endian as target */
 
     mpp->irq_raise = mpic_irq_raise;
     mpp->reset = mpic_reset;
diff --git a/hw/palm.c b/hw/palm.c
index 193aa11d28..f22d7775ee 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -216,14 +216,18 @@ static void palmte_init(ram_addr_t ram_size,
                                  qemu_ram_alloc(NULL, "palmte.flash",
                                                 flash_size) | IO_MEM_ROM);
 
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS0_BASE + flash_size,
                     OMAP_CS0_SIZE - flash_size, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io);
-    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val);
+    io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io);
 
     palmte_microwire_setup(cpu);
@@ -234,20 +238,20 @@ static void palmte_init(ram_addr_t ram_size,
 
     /* Setup initial (reset) machine state */
     if (nb_option_roms) {
-        rom_size = get_image_size(option_rom[0]);
+        rom_size = get_image_size(option_rom[0].name);
         if (rom_size > flash_size) {
             fprintf(stderr, "%s: ROM image too big (%x > %x)\n",
                             __FUNCTION__, rom_size, flash_size);
             rom_size = 0;
         }
         if (rom_size > 0) {
-            rom_size = load_image_targphys(option_rom[0], OMAP_CS0_BASE,
+            rom_size = load_image_targphys(option_rom[0].name, OMAP_CS0_BASE,
                                            flash_size);
             rom_loaded = 1;
         }
         if (rom_size < 0) {
             fprintf(stderr, "%s: error loading '%s'\n",
-                            __FUNCTION__, option_rom[0]);
+                            __FUNCTION__, option_rom[0].name);
         }
     }
 
diff --git a/hw/parallel.c b/hw/parallel.c
index 6b11672e15..ce311aa424 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -481,16 +481,21 @@ static int parallel_isa_initfn(ISADevice *dev)
     if (s->hw_driver) {
         register_ioport_write(base, 8, 1, parallel_ioport_write_hw, s);
         register_ioport_read(base, 8, 1, parallel_ioport_read_hw, s);
+        isa_init_ioport_range(dev, base, 8);
+
         register_ioport_write(base+4, 1, 2, parallel_ioport_eppdata_write_hw2, s);
         register_ioport_read(base+4, 1, 2, parallel_ioport_eppdata_read_hw2, s);
         register_ioport_write(base+4, 1, 4, parallel_ioport_eppdata_write_hw4, s);
         register_ioport_read(base+4, 1, 4, parallel_ioport_eppdata_read_hw4, s);
+        isa_init_ioport(dev, base+4);
         register_ioport_write(base+0x400, 8, 1, parallel_ioport_ecp_write, s);
         register_ioport_read(base+0x400, 8, 1, parallel_ioport_ecp_read, s);
+        isa_init_ioport_range(dev, base+0x400, 8);
     }
     else {
         register_ioport_write(base, 8, 1, parallel_ioport_write_sw, s);
         register_ioport_read(base, 8, 1, parallel_ioport_read_sw, s);
+        isa_init_ioport_range(dev, base, 8);
     }
     return 0;
 }
@@ -577,7 +582,8 @@ ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq
     s->it_shift = it_shift;
     qemu_register_reset(parallel_reset, s);
 
-    io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw, s);
+    io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw,
+                                   s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 8 << it_shift, io_sw);
     return s;
 }
diff --git a/hw/pc.c b/hw/pc.c
index 119c1106c2..e1b2667434 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -733,7 +733,8 @@ static void load_linux(void *fw_cfg,
     fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
     fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
 
-    option_rom[nb_option_roms] = "linuxboot.bin";
+    option_rom[nb_option_roms].name = "linuxboot.bin";
+    option_rom[nb_option_roms].bootindex = 0;
     nb_option_roms++;
 }
 
@@ -937,7 +938,7 @@ void pc_memory_init(ram_addr_t ram_size,
         goto bios_error;
     }
     bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
-    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size));
+    ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
         fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
@@ -969,7 +970,7 @@ void pc_memory_init(ram_addr_t ram_size,
     }
 
     for (i = 0; i < nb_option_roms; i++) {
-        rom_add_option(option_rom[i]);
+        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
     }
 }
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 7d29d43190..a2fb554aa2 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -217,6 +217,14 @@ static QEMUMachine pc_machine = {
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        {
+            .driver   = "PCI",
+            .property = "command_serr_enable",
+            .value    = "off",
+        },
+        { /* end of list */ }
+    },
     .is_default = 1,
 };
 
@@ -265,6 +273,10 @@ static QEMUMachine pc_machine_v0_12 = {
             .driver   = "vmware-svga",
             .property = "rombar",
             .value    = stringify(0),
+        },{
+            .driver   = "PCI",
+            .property = "command_serr_enable",
+            .value    = "off",
         },
         { /* end of list */ }
     }
@@ -300,6 +312,10 @@ static QEMUMachine pc_machine_v0_11 = {
             .driver   = "PCI",
             .property = "rombar",
             .value    = stringify(0),
+        },{
+            .driver   = "PCI",
+            .property = "command_serr_enable",
+            .value    = "off",
         },
         { /* end of list */ }
     }
@@ -347,6 +363,10 @@ static QEMUMachine pc_machine_v0_10 = {
             .driver   = "PCI",
             .property = "rombar",
             .value    = stringify(0),
+        },{
+            .driver   = "PCI",
+            .property = "command_serr_enable",
+            .value    = "off",
         },
         { /* end of list */ }
     },
diff --git a/hw/pci.c b/hw/pci.c
index 0c15b13037..ef00d20d5f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -25,8 +25,6 @@
 #include "pci.h"
 #include "pci_bridge.h"
 #include "pci_internals.h"
-#include "msix.h"
-#include "msi.h"
 #include "monitor.h"
 #include "net.h"
 #include "sysemu.h"
@@ -43,6 +41,7 @@
 
 static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *pcibus_get_dev_path(DeviceState *dev);
+static char *pcibus_get_fw_dev_path(DeviceState *dev);
 static int pcibus_reset(BusState *qbus);
 
 struct BusInfo pci_bus_info = {
@@ -50,6 +49,7 @@ struct BusInfo pci_bus_info = {
     .size       = sizeof(PCIBus),
     .print_dev  = pcibus_dev_print,
     .get_dev_path = pcibus_get_dev_path,
+    .get_fw_dev_path = pcibus_get_fw_dev_path,
     .reset      = pcibus_reset,
     .props      = (Property[]) {
         DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
@@ -57,6 +57,8 @@ struct BusInfo pci_bus_info = {
         DEFINE_PROP_UINT32("rombar",  PCIDevice, rom_bar, 1),
         DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present,
                         QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false),
+        DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present,
+                        QEMU_PCI_CAP_SERR_BITNR, true),
         DEFINE_PROP_END_OF_LIST()
     }
 };
@@ -568,6 +570,9 @@ static void pci_init_wmask(PCIDevice *dev)
     pci_set_word(dev->wmask + PCI_COMMAND,
                  PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
                  PCI_COMMAND_INTX_DISABLE);
+    if (dev->cap_present & QEMU_PCI_CAP_SERR) {
+        pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR);
+    }
 
     memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
            config_size - PCI_CONFIG_HEADER_SIZE);
@@ -1094,68 +1099,69 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
     pci_change_irq_level(pci_dev, irq_num, change);
 }
 
-bool pci_msi_enabled(PCIDevice *dev)
-{
-    return msix_enabled(dev) || msi_enabled(dev);
-}
-
-void pci_msi_notify(PCIDevice *dev, unsigned int vector)
-{
-    if (msix_enabled(dev)) {
-        msix_notify(dev, vector);
-    } else if (msi_enabled(dev)) {
-        msi_notify(dev, vector);
-    } else {
-        /* MSI/MSI-X must be enabled */
-        abort();
-    }
-}
-
 /***********************************************************/
 /* monitor info on PCI */
 
 typedef struct {
     uint16_t class;
     const char *desc;
+    const char *fw_name;
+    uint16_t fw_ign_bits;
 } pci_class_desc;
 
 static const pci_class_desc pci_class_descriptions[] =
 {
-    { 0x0100, "SCSI controller"},
-    { 0x0101, "IDE controller"},
-    { 0x0102, "Floppy controller"},
-    { 0x0103, "IPI controller"},
-    { 0x0104, "RAID controller"},
+    { 0x0001, "VGA controller", "display"},
+    { 0x0100, "SCSI controller", "scsi"},
+    { 0x0101, "IDE controller", "ide"},
+    { 0x0102, "Floppy controller", "fdc"},
+    { 0x0103, "IPI controller", "ipi"},
+    { 0x0104, "RAID controller", "raid"},
     { 0x0106, "SATA controller"},
     { 0x0107, "SAS controller"},
     { 0x0180, "Storage controller"},
-    { 0x0200, "Ethernet controller"},
-    { 0x0201, "Token Ring controller"},
-    { 0x0202, "FDDI controller"},
-    { 0x0203, "ATM controller"},
+    { 0x0200, "Ethernet controller", "ethernet"},
+    { 0x0201, "Token Ring controller", "token-ring"},
+    { 0x0202, "FDDI controller", "fddi"},
+    { 0x0203, "ATM controller", "atm"},
     { 0x0280, "Network controller"},
-    { 0x0300, "VGA controller"},
+    { 0x0300, "VGA controller", "display", 0x00ff},
     { 0x0301, "XGA controller"},
     { 0x0302, "3D controller"},
     { 0x0380, "Display controller"},
-    { 0x0400, "Video controller"},
-    { 0x0401, "Audio controller"},
+    { 0x0400, "Video controller", "video"},
+    { 0x0401, "Audio controller", "sound"},
     { 0x0402, "Phone"},
     { 0x0480, "Multimedia controller"},
-    { 0x0500, "RAM controller"},
-    { 0x0501, "Flash controller"},
+    { 0x0500, "RAM controller", "memory"},
+    { 0x0501, "Flash controller", "flash"},
     { 0x0580, "Memory controller"},
-    { 0x0600, "Host bridge"},
-    { 0x0601, "ISA bridge"},
-    { 0x0602, "EISA bridge"},
-    { 0x0603, "MC bridge"},
-    { 0x0604, "PCI bridge"},
-    { 0x0605, "PCMCIA bridge"},
-    { 0x0606, "NUBUS bridge"},
-    { 0x0607, "CARDBUS bridge"},
+    { 0x0600, "Host bridge", "host"},
+    { 0x0601, "ISA bridge", "isa"},
+    { 0x0602, "EISA bridge", "eisa"},
+    { 0x0603, "MC bridge", "mca"},
+    { 0x0604, "PCI bridge", "pci"},
+    { 0x0605, "PCMCIA bridge", "pcmcia"},
+    { 0x0606, "NUBUS bridge", "nubus"},
+    { 0x0607, "CARDBUS bridge", "cardbus"},
     { 0x0608, "RACEWAY bridge"},
     { 0x0680, "Bridge"},
-    { 0x0c03, "USB controller"},
+    { 0x0700, "Serial port", "serial"},
+    { 0x0701, "Parallel port", "parallel"},
+    { 0x0800, "Interrupt controller", "interrupt-controller"},
+    { 0x0801, "DMA controller", "dma-controller"},
+    { 0x0802, "Timer", "timer"},
+    { 0x0803, "RTC", "rtc"},
+    { 0x0900, "Keyboard", "keyboard"},
+    { 0x0901, "Pen", "pen"},
+    { 0x0902, "Mouse", "mouse"},
+    { 0x0A00, "Dock station", "dock", 0x00ff},
+    { 0x0B00, "i386 cpu", "cpu", 0x00ff},
+    { 0x0c00, "Fireware contorller", "fireware"},
+    { 0x0c01, "Access bus controller", "access-bus"},
+    { 0x0c02, "SSA controller", "ssa"},
+    { 0x0c03, "USB controller", "usb"},
+    { 0x0c04, "Fibre channel controller", "fibre-channel"},
     { 0, NULL}
 };
 
@@ -1812,7 +1818,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
         if (class == 0x0300) {
             rom_add_vga(pdev->romfile);
         } else {
-            rom_add_option(pdev->romfile);
+            rom_add_option(pdev->romfile, -1);
         }
         return 0;
     }
@@ -1960,6 +1966,48 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
     }
 }
 
+static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    const char *name = NULL;
+    const pci_class_desc *desc =  pci_class_descriptions;
+    int class = pci_get_word(d->config + PCI_CLASS_DEVICE);
+
+    while (desc->desc &&
+          (class & ~desc->fw_ign_bits) !=
+          (desc->class & ~desc->fw_ign_bits)) {
+        desc++;
+    }
+
+    if (desc->desc) {
+        name = desc->fw_name;
+    }
+
+    if (name) {
+        pstrcpy(buf, len, name);
+    } else {
+        snprintf(buf, len, "pci%04x,%04x",
+                 pci_get_word(d->config + PCI_VENDOR_ID),
+                 pci_get_word(d->config + PCI_DEVICE_ID));
+    }
+
+    return buf;
+}
+
+static char *pcibus_get_fw_dev_path(DeviceState *dev)
+{
+    PCIDevice *d = (PCIDevice *)dev;
+    char path[50], name[33];
+    int off;
+
+    off = snprintf(path, sizeof(path), "%s@%x",
+                   pci_dev_fw_name(dev, name, sizeof name),
+                   PCI_SLOT(d->devfn));
+    if (PCI_FUNC(d->devfn))
+        snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn));
+    return strdup(path);
+}
+
 static char *pcibus_get_dev_path(DeviceState *dev)
 {
     PCIDevice *d = (PCIDevice *)dev;
diff --git a/hw/pci.h b/hw/pci.h
index 89f7b761e7..aa3afe9684 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -118,6 +118,10 @@ enum {
     /* multifunction capable device */
 #define QEMU_PCI_CAP_MULTIFUNCTION_BITNR        3
     QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR),
+
+    /* command register SERR bit enabled */
+#define QEMU_PCI_CAP_SERR_BITNR 4
+    QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
 };
 
 struct PCIDevice {
@@ -257,9 +261,6 @@ void do_pci_info_print(Monitor *mon, const QObject *data);
 void do_pci_info(Monitor *mon, QObject **ret_data);
 void pci_bridge_update_mappings(PCIBus *b);
 
-bool pci_msi_enabled(PCIDevice *dev);
-void pci_msi_notify(PCIDevice *dev, unsigned int vector);
-
 static inline void
 pci_set_byte(uint8_t *config, uint8_t val)
 {
diff --git a/hw/pci_host.c b/hw/pci_host.c
index bc5b77193d..7c40155b95 100644
--- a/hw/pci_host.c
+++ b/hw/pci_host.c
@@ -78,64 +78,39 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
     return val;
 }
 
-static void pci_host_config_write_swap(ReadWriteHandler *handler,
-                                       pcibus_t addr, uint32_t val, int len)
+static void pci_host_config_write(ReadWriteHandler *handler,
+                                  pcibus_t addr, uint32_t val, int len)
 {
     PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
 
     PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
                 __func__, addr, len, val);
-    val = qemu_bswap_len(val, len);
     s->config_reg = val;
 }
 
-static uint32_t pci_host_config_read_swap(ReadWriteHandler *handler,
-                                          pcibus_t addr, int len)
+static uint32_t pci_host_config_read(ReadWriteHandler *handler,
+                                     pcibus_t addr, int len)
 {
     PCIHostState *s = container_of(handler, PCIHostState, conf_handler);
     uint32_t val = s->config_reg;
 
-    val = qemu_bswap_len(val, len);
     PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
                 __func__, addr, len, val);
     return val;
 }
 
-static void pci_host_config_write_noswap(ReadWriteHandler *handler,
-                                         pcibus_t addr, uint32_t val, int len)
-{
-    PCIHostState *s = container_of(handler, PCIHostState, conf_noswap_handler);
-
-    PCI_DPRINTF("%s addr %" FMT_PCIBUS " %d val %"PRIx32"\n",
-                __func__, addr, len, val);
-    s->config_reg = val;
-}
-
-static uint32_t pci_host_config_read_noswap(ReadWriteHandler *handler,
-                                            pcibus_t addr, int len)
-{
-    PCIHostState *s = container_of(handler, PCIHostState, conf_noswap_handler);
-    uint32_t val = s->config_reg;
-
-    PCI_DPRINTF("%s addr %" FMT_PCIBUS " len %d val %"PRIx32"\n",
-                __func__, addr, len, val);
-    return val;
-}
-
-static void pci_host_data_write_swap(ReadWriteHandler *handler,
-                                     pcibus_t addr, uint32_t val, int len)
+static void pci_host_data_write(ReadWriteHandler *handler,
+                                pcibus_t addr, uint32_t val, int len)
 {
     PCIHostState *s = container_of(handler, PCIHostState, data_handler);
-
-    val = qemu_bswap_len(val, len);
     PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n",
                 addr, len, val);
     if (s->config_reg & (1u << 31))
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
 }
 
-static uint32_t pci_host_data_read_swap(ReadWriteHandler *handler,
-                                        pcibus_t addr, int len)
+static uint32_t pci_host_data_read(ReadWriteHandler *handler,
+                                   pcibus_t addr, int len)
 {
     PCIHostState *s = container_of(handler, PCIHostState, data_handler);
     uint32_t val;
@@ -144,75 +119,41 @@ static uint32_t pci_host_data_read_swap(ReadWriteHandler *handler,
     val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
     PCI_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n",
                 addr, len, val);
-    val = qemu_bswap_len(val, len);
-    return val;
-}
-
-static void pci_host_data_write_noswap(ReadWriteHandler *handler,
-                                       pcibus_t addr, uint32_t val, int len)
-{
-    PCIHostState *s = container_of(handler, PCIHostState, data_noswap_handler);
-    PCI_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n",
-                addr, len, val);
-    if (s->config_reg & (1u << 31))
-        pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
-}
-
-static uint32_t pci_host_data_read_noswap(ReadWriteHandler *handler,
-                                          pcibus_t addr, int len)
-{
-    PCIHostState *s = container_of(handler, PCIHostState, data_noswap_handler);
-    uint32_t val;
-    if (!(s->config_reg & (1 << 31)))
-        return 0xffffffff;
-    val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
-    PCI_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n",
-                addr, len, val);
     return val;
 }
 
 static void pci_host_init(PCIHostState *s)
 {
-    s->conf_handler.write = pci_host_config_write_swap;
-    s->conf_handler.read = pci_host_config_read_swap;
-    s->conf_noswap_handler.write = pci_host_config_write_noswap;
-    s->conf_noswap_handler.read = pci_host_config_read_noswap;
-    s->data_handler.write = pci_host_data_write_swap;
-    s->data_handler.read = pci_host_data_read_swap;
-    s->data_noswap_handler.write = pci_host_data_write_noswap;
-    s->data_noswap_handler.read = pci_host_data_read_noswap;
+    s->conf_handler.write = pci_host_config_write;
+    s->conf_handler.read = pci_host_config_read;
+    s->data_handler.write = pci_host_data_write;
+    s->data_handler.read = pci_host_data_read;
 }
 
-int pci_host_conf_register_mmio(PCIHostState *s, int swap)
+int pci_host_conf_register_mmio(PCIHostState *s, int endian)
 {
     pci_host_init(s);
-    if (swap) {
-        return cpu_register_io_memory_simple(&s->conf_handler);
-    } else {
-        return cpu_register_io_memory_simple(&s->conf_noswap_handler);
-    }
+    return cpu_register_io_memory_simple(&s->conf_handler, endian);
 }
 
 void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s)
 {
     pci_host_init(s);
-    register_ioport_simple(&s->conf_noswap_handler, ioport, 4, 4);
+    register_ioport_simple(&s->conf_handler, ioport, 4, 4);
+    sysbus_init_ioports(&s->busdev, ioport, 4);
 }
 
-int pci_host_data_register_mmio(PCIHostState *s, int swap)
+int pci_host_data_register_mmio(PCIHostState *s, int endian)
 {
     pci_host_init(s);
-    if (swap) {
-        return cpu_register_io_memory_simple(&s->data_handler);
-    } else {
-        return cpu_register_io_memory_simple(&s->data_noswap_handler);
-    }
+    return cpu_register_io_memory_simple(&s->data_handler, endian);
 }
 
 void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
 {
     pci_host_init(s);
-    register_ioport_simple(&s->data_noswap_handler, ioport, 4, 1);
-    register_ioport_simple(&s->data_noswap_handler, ioport, 4, 2);
-    register_ioport_simple(&s->data_noswap_handler, ioport, 4, 4);
+    register_ioport_simple(&s->data_handler, ioport, 4, 1);
+    register_ioport_simple(&s->data_handler, ioport, 4, 2);
+    register_ioport_simple(&s->data_handler, ioport, 4, 4);
+    sysbus_init_ioports(&s->busdev, ioport, 4);
 }
diff --git a/hw/pci_host.h b/hw/pci_host.h
index bd8ede8b72..0a585951e0 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -33,9 +33,7 @@
 
 struct PCIHostState {
     SysBusDevice busdev;
-    ReadWriteHandler conf_noswap_handler;
     ReadWriteHandler conf_handler;
-    ReadWriteHandler data_noswap_handler;
     ReadWriteHandler data_handler;
     uint32_t config_reg;
     PCIBus *bus;
@@ -45,8 +43,8 @@ void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
 
 /* for mmio */
-int pci_host_conf_register_mmio(PCIHostState *s, int swap);
-int pci_host_data_register_mmio(PCIHostState *s, int swap);
+int pci_host_conf_register_mmio(PCIHostState *s, int endian);
+int pci_host_data_register_mmio(PCIHostState *s, int endian);
 
 /* for ioio */
 void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s);
diff --git a/hw/pcie.c b/hw/pcie.c
index f461c1cfbe..d1f0086559 100644
--- a/hw/pcie.c
+++ b/hw/pcie.c
@@ -167,10 +167,12 @@ static void hotplug_event_notify(PCIDevice *dev)
      * The Port may optionally send an MSI when there are hot-plug events that
      * occur while interrupt generation is disabled, and interrupt generation is
      * subsequently enabled. */
-    if (!pci_msi_enabled(dev)) {
+    if (msix_enabled(dev)) {
+        msix_notify(dev, pcie_cap_flags_get_vector(dev));
+    } else if (msi_enabled(dev)) {
+        msi_notify(dev, pcie_cap_flags_get_vector(dev));
+    } else {
         qemu_set_irq(dev->irq[dev->exp.hpev_intx], dev->exp.hpev_notified);
-    } else if (dev->exp.hpev_notified) {
-        pci_msi_notify(dev, pcie_cap_flags_get_vector(dev));
     }
 }
 
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index 47d64003fc..cb97a95d61 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -257,30 +257,49 @@ static unsigned int pcie_aer_root_get_vector(PCIDevice *dev)
     return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT;
 }
 
+/* Given a status register, get corresponding bits in the command register */
+static uint32_t pcie_aer_status_to_cmd(uint32_t status)
+{
+    uint32_t cmd = 0;
+    if (status & PCI_ERR_ROOT_COR_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_COR_EN;
+    }
+    if (status & PCI_ERR_ROOT_NONFATAL_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_NONFATAL_EN;
+    }
+    if (status & PCI_ERR_ROOT_FATAL_RCV) {
+        cmd |= PCI_ERR_ROOT_CMD_FATAL_EN;
+    }
+    return cmd;
+}
+
+static void pcie_aer_root_notify(PCIDevice *dev)
+{
+    if (msix_enabled(dev)) {
+        msix_notify(dev, pcie_aer_root_get_vector(dev));
+    } else if (msi_enabled(dev)) {
+        msi_notify(dev, pcie_aer_root_get_vector(dev));
+    } else {
+        qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
+    }
+}
+
 /*
- * return value:
- * true: error message is sent up
- * false: error message is masked
- *
  * 6.2.6 Error Message Control
  * Figure 6-3
  * root port part
  */
-static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
+static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
 {
-    bool msg_sent;
     uint16_t cmd;
     uint8_t *aer_cap;
     uint32_t root_cmd;
-    uint32_t root_status;
-    bool msi_trigger;
+    uint32_t root_status, prev_status;
 
-    msg_sent = false;
     cmd = pci_get_word(dev->config + PCI_COMMAND);
     aer_cap = dev->config + dev->exp.aer_cap;
     root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
-    root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
-    msi_trigger = false;
+    prev_status = root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
 
     if (cmd & PCI_COMMAND_SERR) {
         /* System Error.
@@ -299,25 +318,14 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
         if (root_status & PCI_ERR_ROOT_COR_RCV) {
             root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
         } else {
-            if (root_cmd & PCI_ERR_ROOT_CMD_COR_EN) {
-                msi_trigger = true;
-            }
             pci_set_word(aer_cap + PCI_ERR_ROOT_COR_SRC, msg->source_id);
         }
         root_status |= PCI_ERR_ROOT_COR_RCV;
         break;
     case PCI_ERR_ROOT_CMD_NONFATAL_EN:
-        if (!(root_status & PCI_ERR_ROOT_NONFATAL_RCV) &&
-            root_cmd & PCI_ERR_ROOT_CMD_NONFATAL_EN) {
-            msi_trigger = true;
-        }
         root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
         break;
     case PCI_ERR_ROOT_CMD_FATAL_EN:
-        if (!(root_status & PCI_ERR_ROOT_FATAL_RCV) &&
-            root_cmd & PCI_ERR_ROOT_CMD_FATAL_EN) {
-            msi_trigger = true;
-        }
         if (!(root_status & PCI_ERR_ROOT_UNCOR_RCV)) {
             root_status |= PCI_ERR_ROOT_FIRST_FATAL;
         }
@@ -337,18 +345,17 @@ static bool pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
     }
     pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status);
 
-    if (root_cmd & msg->severity) {
-        /* 6.2.4.1.2 Interrupt Generation */
-        if (pci_msi_enabled(dev)) {
-            if (msi_trigger) {
-                pci_msi_notify(dev, pcie_aer_root_get_vector(dev));
-            }
-        } else {
-            qemu_set_irq(dev->irq[dev->exp.aer_intx], 1);
-        }
-        msg_sent = true;
+    /* 6.2.4.1.2 Interrupt Generation */
+    /* All the above did was set some bits in the status register.
+     * Specifically these that match message severity.
+     * The below code relies on this fact. */
+    if (!(root_cmd & msg->severity) ||
+        (pcie_aer_status_to_cmd(prev_status) & root_cmd)) {
+        /* Condition is not being set or was already true so nothing to do. */
+        return;
     }
-    return msg_sent;
+
+    pcie_aer_root_notify(dev);
 }
 
 /*
@@ -739,40 +746,26 @@ void pcie_aer_root_reset(PCIDevice *dev)
      */
 }
 
-static bool pcie_aer_root_does_trigger(uint32_t cmd, uint32_t status)
-{
-    return
-        ((cmd & PCI_ERR_ROOT_CMD_COR_EN) && (status & PCI_ERR_ROOT_COR_RCV)) ||
-        ((cmd & PCI_ERR_ROOT_CMD_NONFATAL_EN) &&
-         (status & PCI_ERR_ROOT_NONFATAL_RCV)) ||
-        ((cmd & PCI_ERR_ROOT_CMD_FATAL_EN) &&
-         (status & PCI_ERR_ROOT_FATAL_RCV));
-}
-
 void pcie_aer_root_write_config(PCIDevice *dev,
                                 uint32_t addr, uint32_t val, int len,
                                 uint32_t root_cmd_prev)
 {
     uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
-
-    /* root command register */
+    uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    uint32_t enabled_cmd = pcie_aer_status_to_cmd(root_status);
     uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
-    if (root_cmd & PCI_ERR_ROOT_CMD_EN_MASK) {
-        /* 6.2.4.1.2 Interrupt Generation */
-
-        /* 0 -> 1 */
-        uint32_t root_cmd_set = (root_cmd_prev ^ root_cmd) & root_cmd;
-        uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
+    /* 6.2.4.1.2 Interrupt Generation */
+    if (!msix_enabled(dev) && !msi_enabled(dev)) {
+        qemu_set_irq(dev->irq[dev->exp.aer_intx], !!(root_cmd & enabled_cmd));
+        return;
+    }
 
-        if (pci_msi_enabled(dev)) {
-            if (pcie_aer_root_does_trigger(root_cmd_set, root_status)) {
-                pci_msi_notify(dev, pcie_aer_root_get_vector(dev));
-            }
-        } else {
-            int int_level = pcie_aer_root_does_trigger(root_cmd, root_status);
-            qemu_set_irq(dev->irq[dev->exp.aer_intx], int_level);
-        }
+    if ((root_cmd_prev & enabled_cmd) || !(root_cmd & enabled_cmd)) {
+        /* Send MSI on transition from false to true. */
+        return;
     }
+
+    pcie_aer_root_notify(dev);
 }
 
 static const VMStateDescription vmstate_pcie_aer_err = {
diff --git a/hw/pcie_host.c b/hw/pcie_host.c
index c4feecad71..21069eed83 100644
--- a/hw/pcie_host.c
+++ b/hw/pcie_host.c
@@ -137,7 +137,8 @@ int pcie_host_init(PCIExpressHost *e)
 {
     e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
     e->mmio_index =
-        cpu_register_io_memory(pcie_mmcfg_read, pcie_mmcfg_write, e);
+        cpu_register_io_memory(pcie_mmcfg_read, pcie_mmcfg_write, e,
+                               DEVICE_NATIVE_ENDIAN);
     if (e->mmio_index < 0) {
         return -1;
     }
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 6e4e4062ad..863b485db5 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -436,7 +436,8 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
     s->mask = mask;
 
     vmstate_register(NULL, 0, &vmstate_kbd, s);
-    s_io_memory = cpu_register_io_memory(kbd_mm_read, kbd_mm_write, s);
+    s_io_memory = cpu_register_io_memory(kbd_mm_read, kbd_mm_write, s,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, size, s_io_memory);
 
     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
@@ -484,10 +485,13 @@ static int i8042_initfn(ISADevice *dev)
 
     register_ioport_read(0x60, 1, 1, kbd_read_data, s);
     register_ioport_write(0x60, 1, 1, kbd_write_data, s);
+    isa_init_ioport(dev, 0x60);
     register_ioport_read(0x64, 1, 1, kbd_read_status, s);
     register_ioport_write(0x64, 1, 1, kbd_write_command, s);
+    isa_init_ioport(dev, 0x64);
     register_ioport_read(0x92, 1, 1, ioport92_read, s);
     register_ioport_write(0x92, 1, 1, ioport92_write, s);
+    isa_init_ioport(dev, 0x92);
 
     s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
     s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c
index 3dfbe46472..339a401967 100644
--- a/hw/pcnet-pci.c
+++ b/hw/pcnet-pci.c
@@ -294,7 +294,8 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
 
     /* Handler for memory-mapped I/O */
     s->mmio_index =
-      cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state);
+      cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state,
+                             DEVICE_NATIVE_ENDIAN);
 
     pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
                            PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
@@ -309,7 +310,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev)
     if (!pci_dev->qdev.hotplugged) {
         static int loaded = 0;
         if (!loaded) {
-            rom_add_option("pxe-pcnet.bin");
+            rom_add_option("pxe-pcnet.bin", -1);
             loaded = 1;
         }
     }
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 37010b8fcf..db52dc59e1 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -39,6 +39,7 @@
 #include "net.h"
 #include "qemu-timer.h"
 #include "qemu_socket.h"
+#include "sysemu.h"
 
 #include "pcnet.h"
 
@@ -1740,5 +1741,8 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
+
     return 0;
 }
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 19e13d632d..fb20dfb6ff 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -600,10 +600,12 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
     pfl->storage = qemu_get_ram_ptr(off);
     if (be) {
         pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
-                                             pflash_write_ops_be, pfl);
+                                             pflash_write_ops_be, pfl,
+                                             DEVICE_NATIVE_ENDIAN);
     } else {
         pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
-                                             pflash_write_ops_le, pfl);
+                                             pflash_write_ops_le, pfl,
+                                             DEVICE_NATIVE_ENDIAN);
     }
     pfl->off = off;
     cpu_register_physical_memory(base, total_len,
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index f3d3f41a90..3594a36f8d 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -619,11 +619,11 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
     if (be) {
         pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_be,
                                              pflash_write_ops_be,
-                                             pfl);
+                                             pfl, DEVICE_NATIVE_ENDIAN);
     } else {
         pfl->fl_mem = cpu_register_io_memory(pflash_read_ops_le,
                                              pflash_write_ops_le,
-                                             pfl);
+                                             pfl, DEVICE_NATIVE_ENDIAN);
     }
     pfl->off = off;
     pfl->base = base;
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index b5589b9035..38f9d9eea4 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -365,6 +365,7 @@ static PCIDeviceInfo i440fx_info[] = {
 static SysBusDeviceInfo i440fx_pcihost_info = {
     .init         = i440fx_pcihost_initfn,
     .qdev.name    = "i440FX-pcihost",
+    .qdev.fw_name = "pci",
     .qdev.size    = sizeof(I440FXState),
     .qdev.no_user = 1,
 };
diff --git a/hw/pl011.c b/hw/pl011.c
index 02cf84aee1..77f0dbf137 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -292,7 +292,8 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
 
     iomemtype = cpu_register_io_memory(pl011_readfn,
-                                       pl011_writefn, s);
+                                       pl011_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000,iomemtype);
     sysbus_init_irq(dev, &s->irq);
     s->id = id;
diff --git a/hw/pl022.c b/hw/pl022.c
index d7862bc692..ffe05ab747 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -294,7 +294,8 @@ static int pl022_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(pl022_readfn,
-                                       pl022_writefn, s);
+                                       pl022_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
diff --git a/hw/pl031.c b/hw/pl031.c
index 45b7032c50..e3700c169c 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -189,7 +189,8 @@ static int pl031_init(SysBusDevice *dev)
     pl031_state *s = FROM_SYSBUS(pl031_state, dev);
     struct tm tm;
 
-    iomemtype = cpu_register_io_memory(pl031_readfn, pl031_writefn, s);
+    iomemtype = cpu_register_io_memory(pl031_readfn, pl031_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     if (iomemtype == -1) {
         hw_error("pl031_init: Can't register I/O memory\n");
     }
diff --git a/hw/pl050.c b/hw/pl050.c
index a47786cb0a..057383985e 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -128,7 +128,8 @@ static int pl050_init(SysBusDevice *dev, int is_mouse)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(pl050_readfn,
-                                       pl050_writefn, s);
+                                       pl050_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
     s->is_mouse = is_mouse;
diff --git a/hw/pl061.c b/hw/pl061.c
index e4505f5cb6..1997b7cd2f 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -297,7 +297,8 @@ static int pl061_init(SysBusDevice *dev)
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
 
     iomemtype = cpu_register_io_memory(pl061_readfn,
-                                       pl061_writefn, s);
+                                       pl061_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
     qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
diff --git a/hw/pl080.c b/hw/pl080.c
index 2df65fab94..1a3e06c920 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -325,7 +325,8 @@ static int pl08x_init(SysBusDevice *dev, int nchannels)
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
 
     iomemtype = cpu_register_io_memory(pl080_readfn,
-                                       pl080_writefn, s);
+                                       pl080_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
diff --git a/hw/pl110.c b/hw/pl110.c
index 173458a7cd..a4adb630b0 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -358,7 +358,8 @@ static int pl110_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(pl110_readfn,
-                                       pl110_writefn, s);
+                                       pl110_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq);
     s->ds = graphic_console_init(pl110_update_display,
diff --git a/hw/pl181.c b/hw/pl181.c
index 85cadc4fe1..3e5f92f0e7 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -451,8 +451,8 @@ static int pl181_init(SysBusDevice *dev)
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
     BlockDriverState *bd;
 
-    iomemtype = cpu_register_io_memory(pl181_readfn,
-                                       pl181_writefn, s);
+    iomemtype = cpu_register_io_memory(pl181_readfn, pl181_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
diff --git a/hw/pl190.c b/hw/pl190.c
index a4bc9c15e1..e04e6c17fb 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -233,7 +233,8 @@ static int pl190_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(pl190_readfn,
-                                       pl190_writefn, s);
+                                       pl190_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
     sysbus_init_irq(dev, &s->irq);
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index c5897a9d4d..9abede7e05 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -164,7 +164,8 @@ static void ref405ep_fpga_init (uint32_t base)
 
     fpga = qemu_mallocz(sizeof(ref405ep_fpga_t));
     fpga_memory = cpu_register_io_memory(ref405ep_fpga_read,
-                                         ref405ep_fpga_write, fpga);
+                                         ref405ep_fpga_write, fpga,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00000100, fpga_memory);
     qemu_register_reset(&ref405ep_fpga_reset, fpga);
 }
@@ -488,7 +489,8 @@ static void taihu_cpld_init (uint32_t base)
 
     cpld = qemu_mallocz(sizeof(taihu_cpld_t));
     cpld_memory = cpu_register_io_memory(taihu_cpld_read,
-                                         taihu_cpld_write, cpld);
+                                         taihu_cpld_write, cpld,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00000100, cpld_memory);
     qemu_register_reset(&taihu_cpld_reset, cpld);
 }
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 3600737412..8136cb962b 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -383,7 +383,8 @@ static void ppc4xx_opba_init(target_phys_addr_t base)
 #ifdef DEBUG_OPBA
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    io = cpu_register_io_memory(opba_read, opba_write, opba);
+    io = cpu_register_io_memory(opba_read, opba_write, opba,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x002, io);
     qemu_register_reset(ppc4xx_opba_reset, opba);
 }
@@ -809,7 +810,8 @@ static void ppc405_gpio_init(target_phys_addr_t base)
 #ifdef DEBUG_GPIO
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    io = cpu_register_io_memory(ppc405_gpio_read, ppc405_gpio_write, gpio);
+    io = cpu_register_io_memory(ppc405_gpio_read, ppc405_gpio_write, gpio,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x038, io);
     qemu_register_reset(&ppc405_gpio_reset, gpio);
 }
@@ -1218,7 +1220,8 @@ static void ppc405_i2c_init(target_phys_addr_t base, qemu_irq irq)
 #ifdef DEBUG_I2C
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    io = cpu_register_io_memory(i2c_read, i2c_write, i2c);
+    io = cpu_register_io_memory(i2c_read, i2c_write, i2c,
+                                DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x011, io);
     qemu_register_reset(ppc4xx_i2c_reset, i2c);
 }
@@ -1501,7 +1504,7 @@ static void ppc4xx_gpt_init(target_phys_addr_t base, qemu_irq irqs[5])
 #ifdef DEBUG_GPT
     printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
 #endif
-    io = cpu_register_io_memory(gpt_read, gpt_write, gpt);
+    io = cpu_register_io_memory(gpt_read, gpt_write, gpt, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x0d4, io);
     qemu_register_reset(ppc4xx_gpt_reset, gpt);
 }
diff --git a/hw/ppc440.c b/hw/ppc440.c
index d12cf71814..1ed001a031 100644
--- a/hw/ppc440.c
+++ b/hw/ppc440.c
@@ -85,7 +85,7 @@ CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
     if (!*pcip)
         printf("couldn't create PCI controller!\n");
 
-    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN, 1);
+    isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
 
     if (serial_hds[0] != NULL) {
         serial_mm_init(0xef600300, 0, pic[0], PPC_SERIAL_MM_BAUDBASE,
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 6e437e754e..f62f1f91d5 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -24,7 +24,6 @@
 #include "ppc4xx.h"
 #include "pci.h"
 #include "pci_host.h"
-#include "bswap.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -102,10 +101,6 @@ static void pci4xx_cfgaddr_writel(void *opaque, target_phys_addr_t addr,
 {
     PPC4xxPCIState *ppc4xx_pci = opaque;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
-
     ppc4xx_pci->pci_state.config_reg = value & ~0x3;
 }
 
@@ -120,10 +115,6 @@ static void ppc4xx_pci_reg_write4(void *opaque, target_phys_addr_t offset,
 {
     struct PPC4xxPCIState *pci = opaque;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
-
     /* We ignore all target attempts at PCI configuration, effectively
      * assuming a bidirectional 1:1 mapping of PLB and PCI space. */
 
@@ -251,10 +242,6 @@ static uint32_t ppc4xx_pci_reg_read4(void *opaque, target_phys_addr_t offset)
         value = 0;
     }
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
-
     return value;
 }
 
@@ -372,7 +359,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
 
     /* CFGADDR */
     index = cpu_register_io_memory(pci4xx_cfgaddr_read,
-                                   pci4xx_cfgaddr_write, controller);
+                                   pci4xx_cfgaddr_write, controller,
+                                   DEVICE_LITTLE_ENDIAN);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index);
@@ -384,7 +372,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index);
 
     /* Internal registers */
-    index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller);
+    index = cpu_register_io_memory(pci_reg_read, pci_reg_write, controller,
+                                   DEVICE_LITTLE_ENDIAN);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers, PCI_REG_SIZE, index);
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 305b2d45e6..b9245f066a 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -257,10 +257,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
     isa_mem_base = 0x80000000;
 
     /* Register 8 MB of ISA IO space */
-    isa_mmio_init(0xf2000000, 0x00800000, 1);
+    isa_mmio_init(0xf2000000, 0x00800000);
 
     /* UniN init */
-    unin_memory = cpu_register_io_memory(unin_read, unin_write, NULL);
+    unin_memory = cpu_register_io_memory(unin_read, unin_write, NULL,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
 
     openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 5efc93dc10..8a4e088a38 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -202,7 +202,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     isa_mem_base = 0x80000000;
 
     /* Register 2 MB of ISA IO space */
-    isa_mmio_init(0xfe000000, 0x00200000, 1);
+    isa_mmio_init(0xfe000000, 0x00200000);
 
     /* XXX: we register only 1 output pin for heathrow PIC */
     heathrow_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index b1f9cc74f8..1492266267 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -145,20 +145,12 @@ static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
 
 static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    return bswap16(_PPC_intack_read(addr));
-#else
     return _PPC_intack_read(addr);
-#endif
 }
 
 static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    return bswap32(_PPC_intack_read(addr));
-#else
     return _PPC_intack_read(addr);
-#endif
 }
 
 static CPUWriteMemoryFunc * const PPC_intack_write[] = {
@@ -210,9 +202,6 @@ static void PPC_XCSR_writeb (void *opaque,
 static void PPC_XCSR_writew (void *opaque,
                              target_phys_addr_t addr, uint32_t value)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap16(value);
-#endif
     printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
            value);
 }
@@ -220,9 +209,6 @@ static void PPC_XCSR_writew (void *opaque,
 static void PPC_XCSR_writel (void *opaque,
                              target_phys_addr_t addr, uint32_t value)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
     printf("%s: 0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", __func__, addr,
            value);
 }
@@ -243,9 +229,6 @@ static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
 
     printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
            retval);
-#ifdef TARGET_WORDS_BIGENDIAN
-    retval = bswap16(retval);
-#endif
 
     return retval;
 }
@@ -256,9 +239,6 @@ static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
 
     printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
            retval);
-#ifdef TARGET_WORDS_BIGENDIAN
-    retval = bswap32(retval);
-#endif
 
     return retval;
 }
@@ -484,9 +464,6 @@ static void PPC_prep_io_writew (void *opaque, target_phys_addr_t addr,
     sysctrl_t *sysctrl = opaque;
 
     addr = prep_IO_address(sysctrl, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap16(value);
-#endif
     PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
     cpu_outw(addr, value);
 }
@@ -498,9 +475,6 @@ static uint32_t PPC_prep_io_readw (void *opaque, target_phys_addr_t addr)
 
     addr = prep_IO_address(sysctrl, addr);
     ret = cpu_inw(addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap16(ret);
-#endif
     PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
 
     return ret;
@@ -512,9 +486,6 @@ static void PPC_prep_io_writel (void *opaque, target_phys_addr_t addr,
     sysctrl_t *sysctrl = opaque;
 
     addr = prep_IO_address(sysctrl, addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    value = bswap32(value);
-#endif
     PPC_IO_DPRINTF("0x" TARGET_FMT_plx " => 0x%08" PRIx32 "\n", addr, value);
     cpu_outl(addr, value);
 }
@@ -526,9 +497,6 @@ static uint32_t PPC_prep_io_readl (void *opaque, target_phys_addr_t addr)
 
     addr = prep_IO_address(sysctrl, addr);
     ret = cpu_inl(addr);
-#ifdef TARGET_WORDS_BIGENDIAN
-    ret = bswap32(ret);
-#endif
     PPC_IO_DPRINTF("0x" TARGET_FMT_plx " <= 0x%08" PRIx32 "\n", addr, ret);
 
     return ret;
@@ -690,7 +658,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
     //    pci_bus = i440fx_init();
     /* Register 8 MB of ISA IO space (needed for non-contiguous map) */
     PPC_io_memory = cpu_register_io_memory(PPC_prep_io_read,
-                                           PPC_prep_io_write, sysctrl);
+                                           PPC_prep_io_write, sysctrl,
+                                           DEVICE_LITTLE_ENDIAN);
     cpu_register_physical_memory(0x80000000, 0x00800000, PPC_io_memory);
 
     /* init basic PC hardware */
@@ -755,12 +724,13 @@ static void ppc_prep_init (ram_addr_t ram_size,
     register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
     /* PCI intack location */
     PPC_io_memory = cpu_register_io_memory(PPC_intack_read,
-                                           PPC_intack_write, NULL);
+                                           PPC_intack_write, NULL,
+                                           DEVICE_LITTLE_ENDIAN);
     cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
     /* PowerPC control and status register group */
 #if 0
     PPC_io_memory = cpu_register_io_memory(PPC_XCSR_read, PPC_XCSR_write,
-                                           NULL);
+                                           NULL, DEVICE_LITTLE_ENDIAN);
     cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
 #endif
 
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 59d20d30ae..b7670ae27c 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -220,7 +220,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     if (!pci_bus)
         printf("couldn't create PCI controller!\n");
 
-    isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN, 1);
+    isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);
 
     if (pci_bus) {
         /* Register network interfaces. */
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 8ac99f2817..11edd03f16 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -292,19 +292,22 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
     controller->pci_dev = d;
 
     /* CFGADDR */
-    index = pci_host_conf_register_mmio(&controller->pci_state, 0);
+    index = pci_host_conf_register_mmio(&controller->pci_state,
+                                        DEVICE_BIG_ENDIAN);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index);
 
     /* CFGDATA */
-    index = pci_host_data_register_mmio(&controller->pci_state, 0);
+    index = pci_host_data_register_mmio(&controller->pci_state,
+                                        DEVICE_BIG_ENDIAN);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index);
 
     index = cpu_register_io_memory(e500_pci_reg_read,
-                                   e500_pci_reg_write, controller);
+                                   e500_pci_reg_write, controller,
+                                   DEVICE_NATIVE_ENDIAN);
     if (index < 0)
         goto free;
     cpu_register_physical_memory(registers + PCIE500_REG_BASE,
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 0c2afe9c85..f88b8254c2 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -125,7 +125,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
     pci_host_data_register_ioport(0xcfc, s);
 
     PPC_io_memory = cpu_register_io_memory(PPC_PCIIO_read,
-                                           PPC_PCIIO_write, s);
+                                           PPC_PCIIO_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
 
     /* PCI host bridge */
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 6e046450df..ab524a779a 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -859,7 +859,8 @@ static int pxa2xx_ssp_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     iomemtype = cpu_register_io_memory(pxa2xx_ssp_readfn,
-                                       pxa2xx_ssp_writefn, s);
+                                       pxa2xx_ssp_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
@@ -1512,7 +1513,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
     s->offset = base - (base & (~region_size) & TARGET_PAGE_MASK);
 
     iomemtype = cpu_register_io_memory(pxa2xx_i2c_readfn,
-                    pxa2xx_i2c_writefn, s);
+                    pxa2xx_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base & ~region_size,
                     region_size + 1, iomemtype);
 
@@ -1749,7 +1750,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
     pxa2xx_i2s_reset(s);
 
     iomemtype = cpu_register_io_memory(pxa2xx_i2s_readfn,
-                    pxa2xx_i2s_writefn, s);
+                    pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x100000, iomemtype);
 
     register_savevm(NULL, "pxa2xx_i2s", base, 0,
@@ -2009,7 +2010,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
     pxa2xx_fir_reset(s);
 
     iomemtype = cpu_register_io_memory(pxa2xx_fir_readfn,
-                    pxa2xx_fir_writefn, s);
+                    pxa2xx_fir_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x1000, iomemtype);
 
     if (chr)
@@ -2102,7 +2103,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
-                    pxa2xx_cm_writefn, s);
+                    pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
     register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
@@ -2113,13 +2114,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
-                    pxa2xx_mm_writefn, s);
+                    pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
     register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
-                    pxa2xx_pm_writefn, s);
+                    pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
     register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
@@ -2142,7 +2143,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     s->rtc_base = 0x40900000;
     iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s);
+                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
     register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
@@ -2225,7 +2226,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     s->cm_regs[CCCR >> 2] = 0x02000210;	/* 416.0 MHz */
     s->clkcfg = 0x00000009;		/* Turbo mode active */
     iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
-                    pxa2xx_cm_writefn, s);
+                    pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
     register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
@@ -2236,13 +2237,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     s->mm_regs[MDREFR >> 2] = 0x03ca4000;
     s->mm_regs[MECR >> 2] = 0x00000001;	/* Two PC Card sockets */
     iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
-                    pxa2xx_mm_writefn, s);
+                    pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
     register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     s->pm_base = 0x40f00000;
     iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
-                    pxa2xx_pm_writefn, s);
+                    pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
     register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
@@ -2265,7 +2266,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     s->rtc_base = 0x40900000;
     iomemtype = cpu_register_io_memory(pxa2xx_rtc_readfn,
-                    pxa2xx_rtc_writefn, s);
+                    pxa2xx_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(s->rtc_base, 0x1000, iomemtype);
     pxa2xx_rtc_init(s);
     register_savevm(NULL, "pxa2xx_rtc", 0, 0, pxa2xx_rtc_save,
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 9c479df04e..b512d34501 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -504,7 +504,7 @@ static PXA2xxDMAState *pxa2xx_dma_init(target_phys_addr_t base,
     memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
     iomemtype = cpu_register_io_memory(pxa2xx_dma_readfn,
-                    pxa2xx_dma_writefn, s);
+                    pxa2xx_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00010000, iomemtype);
 
     register_savevm(NULL, "pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 2abcb6543a..0d034462d2 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -309,7 +309,7 @@ PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
     s->in = qemu_allocate_irqs(pxa2xx_gpio_set, s, lines);
 
     iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
-                    pxa2xx_gpio_writefn, s);
+                    pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
     register_savevm(NULL, "pxa2xx_gpio", 0, 0,
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index dfa8945b22..4c999171b9 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -314,7 +314,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
     s->irq = irq;
 
     iomemtype = cpu_register_io_memory(pxa2xx_keypad_readfn,
-                    pxa2xx_keypad_writefn, s);
+                    pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
     register_savevm(NULL, "pxa2xx_keypad", 0, 0,
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 111a0dc031..1f2211a2f0 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -929,7 +929,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
     pxa2xx_lcdc_orientation(s, graphic_rotate);
 
     iomemtype = cpu_register_io_memory(pxa2xx_lcdc_readfn,
-                    pxa2xx_lcdc_writefn, s);
+                    pxa2xx_lcdc_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
     s->ds = graphic_console_init(pxa2xx_update_display,
diff --git a/hw/pxa2xx_mmci.c b/hw/pxa2xx_mmci.c
index ca98660224..24d409d1a1 100644
--- a/hw/pxa2xx_mmci.c
+++ b/hw/pxa2xx_mmci.c
@@ -528,7 +528,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(target_phys_addr_t base,
     s->dma = dma;
 
     iomemtype = cpu_register_io_memory(pxa2xx_mmci_readfn,
-                    pxa2xx_mmci_writefn, s);
+                    pxa2xx_mmci_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
     /* Instantiate the actual storage */
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index be1309f62e..50d4649f60 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -140,19 +140,19 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
 
     /* Socket I/O Memory Space */
     iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
-                    pxa2xx_pcmcia_io_writefn, s);
+                    pxa2xx_pcmcia_io_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
 
     /* Then next 64 MB is reserved */
 
     /* Socket Attribute Memory Space */
     iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn,
-                    pxa2xx_pcmcia_attr_writefn, s);
+                    pxa2xx_pcmcia_attr_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
 
     /* Socket Common Memory Space */
     iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn,
-                    pxa2xx_pcmcia_common_writefn, s);
+                    pxa2xx_pcmcia_common_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
 
     if (base == 0x30000000)
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 4d8944bfce..a36da233d3 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -300,7 +300,7 @@ qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 
     /* Enable IC memory-mapped registers access.  */
     iomemtype = cpu_register_io_memory(pxa2xx_pic_readfn,
-                    pxa2xx_pic_writefn, s);
+                    pxa2xx_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00100000, iomemtype);
 
     /* Enable IC coprocessor access.  */
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 0f0ffd3f36..b556d11870 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -452,7 +452,7 @@ static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
     }
 
     iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
-                    pxa2xx_timer_writefn, s);
+                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
 
     register_savevm(NULL, "pxa2xx_timer", 0, 0,
diff --git a/hw/qdev.c b/hw/qdev.c
index b65b63e10e..10e28df7a1 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -889,3 +889,35 @@ int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
     return qdev_unplug(dev);
 }
+
+static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
+{
+    int l = 0;
+
+    if (dev && dev->parent_bus) {
+        char *d;
+        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+        if (dev->parent_bus->info->get_fw_dev_path) {
+            d = dev->parent_bus->info->get_fw_dev_path(dev);
+            l += snprintf(p + l, size - l, "%s", d);
+            qemu_free(d);
+        } else {
+            l += snprintf(p + l, size - l, "%s", dev->info->name);
+        }
+    }
+    l += snprintf(p + l , size - l, "/");
+
+    return l;
+}
+
+char* qdev_get_fw_dev_path(DeviceState *dev)
+{
+    char path[128];
+    int l;
+
+    l = qdev_get_fw_dev_path_helper(dev, path, 128);
+
+    path[l-1] = '\0';
+
+    return strdup(path);
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index 3fac364c6b..aaaf55ab26 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -49,6 +49,12 @@ struct DeviceState {
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
 typedef char *(*bus_get_dev_path)(DeviceState *dev);
+/*
+ * This callback is used to create Open Firmware device path in accordance with
+ * OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings
+ * can be found here http://playground.sun.com/1275/bindings/.
+ */
+typedef char *(*bus_get_fw_dev_path)(DeviceState *dev);
 typedef int (qbus_resetfn)(BusState *bus);
 
 struct BusInfo {
@@ -56,6 +62,7 @@ struct BusInfo {
     size_t size;
     bus_dev_printfn print_dev;
     bus_get_dev_path get_dev_path;
+    bus_get_fw_dev_path get_fw_dev_path;
     qbus_resetfn *reset;
     Property *props;
 };
@@ -141,6 +148,7 @@ typedef void (*qdev_resetfn)(DeviceState *dev);
 
 struct DeviceInfo {
     const char *name;
+    const char *fw_name;
     const char *alias;
     const char *desc;
     size_t size;
@@ -306,6 +314,12 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props);
 void qdev_prop_register_global_list(GlobalProperty *props);
 void qdev_prop_set_globals(DeviceState *dev);
 
+static inline const char *qdev_fw_name(DeviceState *dev)
+{
+    return dev->info->fw_name ? : dev->info->alias ? : dev->info->name;
+}
+
+char *qdev_get_fw_dev_path(DeviceState *dev);
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 extern struct BusInfo system_bus_info;
 
diff --git a/hw/r2d.c b/hw/r2d.c
index a58f653e52..c4f32ef49d 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -189,7 +189,8 @@ static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
     s->irl = irl;
 
     iomemtype = cpu_register_io_memory(r2d_fpga_readfn,
-				       r2d_fpga_writefn, s);
+				       r2d_fpga_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x40, iomemtype);
     return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
 }
diff --git a/hw/rc4030.c b/hw/rc4030.c
index abbc3eb4e2..0a9d98d1d5 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -819,9 +819,11 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
     register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
     rc4030_reset(s);
 
-    s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s);
+    s_chipset = cpu_register_io_memory(rc4030_read, rc4030_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
-    s_jazzio = cpu_register_io_memory(jazzio_read, jazzio_write, s);
+    s_jazzio = cpu_register_io_memory(jazzio_read, jazzio_write, s,
+                                      DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
 
     return s;
diff --git a/hw/realview.c b/hw/realview.c
index e9fcbc9a6d..6eb6c6a1f1 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -81,7 +81,8 @@ static int realview_i2c_init(SysBusDevice *dev)
     bus = i2c_init_bus(&dev->qdev, "i2c");
     s->bitbang = bitbang_i2c_init(bus);
     iomemtype = cpu_register_io_memory(realview_i2c_readfn,
-                                       realview_i2c_writefn, s);
+                                       realview_i2c_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     return 0;
 }
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index bd02b095e8..db908b6439 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -64,7 +64,8 @@ static int realview_gic_init(SysBusDevice *dev)
 
     gic_init(&s->gic);
     s->iomemtype = cpu_register_io_memory(realview_gic_cpu_readfn,
-                                          realview_gic_cpu_writefn, s);
+                                          realview_gic_cpu_writefn, s,
+                                          DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x2000, realview_gic_map);
     return 0;
 }
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d92981dc0d..a8aed89074 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -52,6 +52,7 @@
 #include "qemu-timer.h"
 #include "net.h"
 #include "loader.h"
+#include "sysemu.h"
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
@@ -3125,17 +3126,11 @@ static void rtl8139_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t
 
 static void rtl8139_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
     rtl8139_io_writew(opaque, addr & 0xFF, val);
 }
 
 static void rtl8139_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
     rtl8139_io_writel(opaque, addr & 0xFF, val);
 }
 
@@ -3147,18 +3142,12 @@ static uint32_t rtl8139_mmio_readb(void *opaque, target_phys_addr_t addr)
 static uint32_t rtl8139_mmio_readw(void *opaque, target_phys_addr_t addr)
 {
     uint32_t val = rtl8139_io_readw(opaque, addr & 0xFF);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
     return val;
 }
 
 static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
 {
     uint32_t val = rtl8139_io_readl(opaque, addr & 0xFF);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
     return val;
 }
 
@@ -3366,7 +3355,8 @@ static int pci_rtl8139_init(PCIDevice *dev)
 
     /* I/O handler for memory-mapped I/O */
     s->rtl8139_mmio_io_addr =
-        cpu_register_io_memory(rtl8139_mmio_read, rtl8139_mmio_write, s);
+        cpu_register_io_memory(rtl8139_mmio_read, rtl8139_mmio_write, s,
+                               DEVICE_LITTLE_ENDIAN);
 
     pci_register_bar(&s->dev, 0, 0x100,
                            PCI_BASE_ADDRESS_SPACE_IO,  rtl8139_ioport_map);
@@ -3387,6 +3377,9 @@ static int pci_rtl8139_init(PCIDevice *dev)
     s->TimerExpire = 0;
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
     rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+
+    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet-phy@0");
+
     return 0;
 }
 
diff --git a/hw/sb16.c b/hw/sb16.c
index 78590a76f1..c9d37ad2b7 100644
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -1368,16 +1368,20 @@ static int sb16_initfn (ISADevice *dev)
 
     for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
         register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
+        isa_init_ioport(dev, s->port + dsp_write_ports[i]);
     }
 
     for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
         register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
+        isa_init_ioport(dev, s->port + dsp_read_ports[i]);
     }
 
     register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
     register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
+    isa_init_ioport(dev, s->port + 0x4);
     register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
     register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
+    isa_init_ioport(dev, s->port + 0x5);
 
     DMA_register_channel (s->hdma, SB_read_DMA, s);
     DMA_register_channel (s->dma, SB_read_DMA, s);
diff --git a/hw/sbi.c b/hw/sbi.c
index c4adc09fa9..53f66f2c5e 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -125,7 +125,8 @@ static int sbi_init1(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->cpu_irqs[i]);
     }
 
-    sbi_io_memory = cpu_register_io_memory(sbi_mem_read, sbi_mem_write, s);
+    sbi_io_memory = cpu_register_io_memory(sbi_mem_read, sbi_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, SBI_SIZE, sbi_io_memory);
 
     return 0;
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 93f0e9abc1..7febb86e77 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -5,9 +5,12 @@
 #include "qdev.h"
 #include "blockdev.h"
 
+static char *scsibus_get_fw_dev_path(DeviceState *dev);
+
 static struct BusInfo scsi_bus_info = {
     .name  = "SCSI",
     .size  = sizeof(SCSIBus),
+    .get_fw_dev_path = scsibus_get_fw_dev_path,
     .props = (Property[]) {
         DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1),
         DEFINE_PROP_END_OF_LIST(),
@@ -518,3 +521,23 @@ void scsi_req_complete(SCSIRequest *req)
                        req->tag,
                        req->status);
 }
+
+static char *scsibus_get_fw_dev_path(DeviceState *dev)
+{
+    SCSIDevice *d = (SCSIDevice*)dev;
+    SCSIBus *bus = scsi_bus_from_device(d);
+    char path[100];
+    int i;
+
+    for (i = 0; i < bus->ndev; i++) {
+        if (bus->devs[i] == d) {
+            break;
+        }
+    }
+
+    assert(i != bus->ndev);
+
+    snprintf(path, sizeof(path), "%s@%x", qdev_fw_name(dev), i);
+
+    return strdup(path);
+}
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6e49404d87..87f9e8677e 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1225,11 +1225,13 @@ static int scsi_disk_initfn(SCSIDevice *dev)
     s->qdev.type = TYPE_DISK;
     qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s);
     bdrv_set_removable(s->bs, is_cd);
+    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
     return 0;
 }
 
 static SCSIDeviceInfo scsi_disk_info = {
     .qdev.name    = "scsi-disk",
+    .qdev.fw_name = "disk",
     .qdev.desc    = "virtual scsi disk or cdrom",
     .qdev.size    = sizeof(SCSIDiskState),
     .qdev.reset   = scsi_disk_reset,
diff --git a/hw/serial.c b/hw/serial.c
index 9ebc452aea..2c4af61a2b 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -778,6 +778,7 @@ static int serial_isa_initfn(ISADevice *dev)
 
     register_ioport_write(isa->iobase, 8, 1, serial_ioport_write, s);
     register_ioport_read(isa->iobase, 8, 1, serial_ioport_read, s);
+    isa_init_ioport_range(dev, isa->iobase, 8);
     return 0;
 }
 
@@ -955,10 +956,12 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     if (ioregister) {
         if (be) {
             s_io_memory = cpu_register_io_memory(serial_mm_read_be,
-                                                 serial_mm_write_be, s);
+                                                 serial_mm_write_be, s,
+                                                 DEVICE_NATIVE_ENDIAN);
         } else {
             s_io_memory = cpu_register_io_memory(serial_mm_read_le,
-                                                 serial_mm_write_le, s);
+                                                 serial_mm_write_le, s,
+                                                 DEVICE_NATIVE_ENDIAN);
         }
         cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
     }
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 0291d5fd49..9e54ad1904 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -713,7 +713,8 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
     s->cpu = cpu;
     s->periph_freq = 60000000;	/* 60MHz */
     sh7750_io_memory = cpu_register_io_memory(sh7750_mem_read,
-					      sh7750_mem_write, s);
+					      sh7750_mem_write, s,
+                                              DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory_offset(0x1f000000, 0x1000,
                                         sh7750_io_memory, 0x1f000000);
     cpu_register_physical_memory_offset(0xff000000, 0x1000,
@@ -728,7 +729,8 @@ SH7750State *sh7750_init(CPUSH4State * cpu)
                                         sh7750_io_memory, 0x1fc00000);
 
     sh7750_mm_cache_and_tlb = cpu_register_io_memory(sh7750_mmct_read,
-						     sh7750_mmct_write, s);
+						     sh7750_mmct_write, s,
+                                                     DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0xf0000000, 0x08000000,
 				 sh7750_mm_cache_and_tlb);
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index d3f5ea57d5..0734da90f0 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -442,7 +442,8 @@ int sh_intc_init(struct intc_desc *desc,
     desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources);
  
     desc->iomemtype = cpu_register_io_memory(sh_intc_readfn,
-					     sh_intc_writefn, desc);
+					     sh_intc_writefn, desc,
+                                             DEVICE_NATIVE_ENDIAN);
     if (desc->mask_regs) {
         for (i = 0; i < desc->nr_mask_regs; i++) {
 	    struct intc_mask_reg *mr = desc->mask_regs + i;
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index cc2f190529..072078be51 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -54,7 +54,7 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
             cpu_register_physical_memory(pcic->iobr & 0xfffc0000, 0x40000,
                                          IO_MEM_UNASSIGNED);
             pcic->iobr = val & 0xfffc0001;
-            isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000, 0);
+            isa_mmio_init(pcic->iobr & 0xfffc0000, 0x40000);
         }
         break;
     case 0x220:
@@ -103,12 +103,13 @@ PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
 
     p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
                                  -1, NULL, NULL);
-    reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p);
+    reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p,
+                                 DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(0x1e200000, 0x224, reg);
     cpu_register_physical_memory(0xfe200000, 0x224, reg);
 
     p->iobr = 0xfe240000;
-    isa_mmio_init(p->iobr, 0x40000, 0);
+    isa_mmio_init(p->iobr, 0x40000);
 
     pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
     pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 93dc144a34..1bdc0a5ab2 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -395,7 +395,8 @@ void sh_serial_init (target_phys_addr_t base, int feat,
     sh_serial_clear_fifo(s);
 
     s_io_memory = cpu_register_io_memory(sh_serial_readfn,
-					 sh_serial_writefn, s);
+					 sh_serial_writefn, s,
+                                         DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(P4ADDR(base), 0x28, s_io_memory);
     cpu_register_physical_memory(A7ADDR(base), 0x28, s_io_memory);
 
diff --git a/hw/sh_timer.c b/hw/sh_timer.c
index fd2146a0c9..5eec6b7c14 100644
--- a/hw/sh_timer.c
+++ b/hw/sh_timer.c
@@ -319,7 +319,8 @@ void tmu012_init(target_phys_addr_t base, int feat, uint32_t freq,
         s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT,
 				    ch2_irq0); /* ch2_irq1 not supported */
     iomemtype = cpu_register_io_memory(tmu012_readfn,
-                                       tmu012_writefn, s);
+                                       tmu012_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(P4ADDR(base), 0x00001000, iomemtype);
     cpu_register_physical_memory(A7ADDR(base), 0x00001000, iomemtype);
     /* ??? Save/restore.  */
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 9d5ad86d98..fd69354bb3 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -422,7 +422,8 @@ static int slavio_intctl_init1(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
     io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
-                                       slavio_intctlm_mem_write, s);
+                                       slavio_intctlm_mem_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
 
     for (i = 0; i < MAX_CPUS; i++) {
@@ -431,7 +432,8 @@ static int slavio_intctl_init1(SysBusDevice *dev)
         }
         io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
                                            slavio_intctl_mem_write,
-                                           &s->slaves[i]);
+                                           &s->slaves[i],
+                                           DEVICE_NATIVE_ENDIAN);
         sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
         s->slaves[i].cpu = i;
         s->slaves[i].master = s;
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 1d81a633c7..198360d573 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -412,7 +412,8 @@ static int apc_init1(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->cpu_halt);
 
     /* Power management (APC) XXX: not a Slavio device */
-    io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s);
+    io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
     return 0;
 }
@@ -428,39 +429,46 @@ static int slavio_misc_init1(SysBusDevice *dev)
     /* 8 bit registers */
     /* Slavio control */
     io = cpu_register_io_memory(slavio_cfg_mem_read,
-                                slavio_cfg_mem_write, s);
+                                slavio_cfg_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     /* Diagnostics */
     io = cpu_register_io_memory(slavio_diag_mem_read,
-                                slavio_diag_mem_write, s);
+                                slavio_diag_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     /* Modem control */
     io = cpu_register_io_memory(slavio_mdm_mem_read,
-                                slavio_mdm_mem_write, s);
+                                slavio_mdm_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     /* 16 bit registers */
     /* ss600mp diag LEDs */
     io = cpu_register_io_memory(slavio_led_mem_read,
-                                slavio_led_mem_write, s);
+                                slavio_led_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     /* 32 bit registers */
     /* System control */
     io = cpu_register_io_memory(slavio_sysctrl_mem_read,
-                                slavio_sysctrl_mem_write, s);
+                                slavio_sysctrl_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, SYSCTRL_SIZE, io);
 
     /* AUX 1 (Misc System Functions) */
     io = cpu_register_io_memory(slavio_aux1_mem_read,
-                                slavio_aux1_mem_write, s);
+                                slavio_aux1_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     /* AUX 2 (Software Powerdown Control) */
     io = cpu_register_io_memory(slavio_aux2_mem_read,
-                                slavio_aux2_mem_write, s);
+                                slavio_aux2_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, MISC_SIZE, io);
 
     qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 13f1e62ad8..5511313687 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -390,7 +390,8 @@ static int slavio_timer_init1(SysBusDevice *dev)
         ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 
         io = cpu_register_io_memory(slavio_timer_mem_read,
-                                    slavio_timer_mem_write, tc);
+                                    slavio_timer_mem_write, tc,
+                                    DEVICE_NATIVE_ENDIAN);
         if (i == 0) {
             sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
         } else {
diff --git a/hw/sm501.c b/hw/sm501.c
index 705e0a5c76..f16e6e4e65 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1379,15 +1379,18 @@ void sm501_init(uint32_t base, uint32_t local_mem_bytes, qemu_irq irq,
     /* map mmio */
     sm501_system_config_index
 	= cpu_register_io_memory(sm501_system_config_readfn,
-				 sm501_system_config_writefn, s);
+				 sm501_system_config_writefn, s,
+                                 DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET,
 				 0x6c, sm501_system_config_index);
     sm501_disp_ctrl_index = cpu_register_io_memory(sm501_disp_ctrl_readfn,
-						   sm501_disp_ctrl_writefn, s);
+						   sm501_disp_ctrl_writefn, s,
+                                                   DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_DC,
                                  0x1000, sm501_disp_ctrl_index);
     sm501_2d_engine_index = cpu_register_io_memory(sm501_2d_engine_readfn,
-                                                   sm501_2d_engine_writefn, s);
+                                                   sm501_2d_engine_writefn, s,
+                                                   DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base + MMIO_BASE_OFFSET + SM501_2D_ENGINE,
                                  0x54, sm501_2d_engine_index);
 
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index f7d58e1262..fc714d7f28 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -719,7 +719,8 @@ static int smc91c111_init1(SysBusDevice *dev)
     smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
 
     s->mmio_index = cpu_register_io_memory(smc91c111_readfn,
-                                           smc91c111_writefn, s);
+                                           smc91c111_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 16, s->mmio_index);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 0904188c95..e78f02547f 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -257,7 +257,8 @@ static int sparc32_dma_init1(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
 
-    dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s);
+    dma_io_memory = cpu_register_io_memory(dma_mem_read, dma_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, DMA_SIZE, dma_io_memory);
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
diff --git a/hw/spitz.c b/hw/spitz.c
index a064460936..092bb64eac 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -176,7 +176,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
         s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
 
     iomemtype = cpu_register_io_memory(sl_readfn,
-                    sl_writefn, s);
+                    sl_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
 
     register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
diff --git a/hw/stellaris.c b/hw/stellaris.c
index ccad1348a9..b90327305a 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -348,7 +348,8 @@ static int stellaris_gptm_init(SysBusDevice *dev)
     qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
 
     iomemtype = cpu_register_io_memory(gptm_readfn,
-                                       gptm_writefn, s);
+                                       gptm_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     s->opaque[0] = s->opaque[1] = s;
@@ -671,7 +672,8 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
     s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16);
 
     iomemtype = cpu_register_io_memory(ssys_readfn,
-                                       ssys_writefn, s);
+                                       ssys_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
     register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
@@ -884,7 +886,8 @@ static int stellaris_i2c_init(SysBusDevice * dev)
     s->bus = bus;
 
     iomemtype = cpu_register_io_memory(stellaris_i2c_readfn,
-                                       stellaris_i2c_writefn, s);
+                                       stellaris_i2c_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? For now we only implement the master interface.  */
     stellaris_i2c_reset(s);
@@ -1193,7 +1196,8 @@ static int stellaris_adc_init(SysBusDevice *dev)
     }
 
     iomemtype = cpu_register_io_memory(stellaris_adc_readfn,
-                                       stellaris_adc_writefn, s);
+                                       stellaris_adc_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     stellaris_adc_reset(s);
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 330a9d6130..6a0583a256 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -409,7 +409,8 @@ static int stellaris_enet_init(SysBusDevice *dev)
     stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
 
     s->mmio_index = cpu_register_io_memory(stellaris_enet_readfn,
-                                           stellaris_enet_writefn, s);
+                                           stellaris_enet_writefn, s,
+                                           DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, s->mmio_index);
     sysbus_init_irq(dev, &s->irq);
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 7d7542dc9f..5c7fdeffb4 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -196,7 +196,8 @@ static int sun4c_intctl_init1(SysBusDevice *dev)
     unsigned int i;
 
     io_memory = cpu_register_io_memory(sun4c_intctl_mem_read,
-                                       sun4c_intctl_mem_write, s);
+                                       sun4c_intctl_mem_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
     qdev_init_gpio_in(&dev->qdev, sun4c_set_irq, 8);
 
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 720ee3f0bd..bba69eef92 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -351,7 +351,8 @@ static int iommu_init1(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
 
-    io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s);
+    io = cpu_register_io_memory(iommu_mem_read, iommu_mem_write, s,
+                                DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, IOMMU_NREGS * sizeof(uint32_t), io);
 
     return 0;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 5292ac670f..90b1ce2770 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -525,10 +525,10 @@ static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
                  region_num, addr);
     switch (region_num) {
     case 0:
-        isa_mmio_init(addr, 0x1000000, 1);
+        isa_mmio_init(addr, 0x1000000);
         break;
     case 1:
-        isa_mmio_init(addr, 0x800000, 1);
+        isa_mmio_init(addr, 0x800000);
         break;
     }
 }
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index ed57203f92..7e37364540 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -510,7 +510,8 @@ static int syborg_fb_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_fb_readfn,
-                                       syborg_fb_writefn, s);
+                                       syborg_fb_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     s->ds = graphic_console_init(syborg_fb_update_display,
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index 30140fba47..5217983f6c 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -210,7 +210,8 @@ static int syborg_int_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->parent_irq);
     qdev_init_gpio_in(&dev->qdev, syborg_int_set_irq, s->num_irqs);
     iomemtype = cpu_register_io_memory(syborg_int_readfn,
-                                       syborg_int_writefn, s);
+                                       syborg_int_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
 
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 7709100c14..d295e99ebd 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -210,7 +210,8 @@ static int syborg_keyboard_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
-                                       syborg_keyboard_writefn, s);
+                                       syborg_keyboard_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     if (s->fifo_size <= 0) {
         fprintf(stderr, "syborg_keyboard: fifo too small\n");
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index 69b8d96bba..a886888467 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -206,7 +206,8 @@ static int syborg_pointer_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_pointer_readfn,
-				       syborg_pointer_writefn, s);
+				       syborg_pointer_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     if (s->fifo_size <= 0) {
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 78d5edb0f7..329aa42661 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -130,7 +130,8 @@ static int syborg_rtc_init(SysBusDevice *dev)
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(syborg_rtc_readfn,
-                                       syborg_rtc_writefn, s);
+                                       syborg_rtc_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     qemu_get_timedate(&tm, 0);
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index 8c429563a2..34ce076d45 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -322,7 +322,8 @@ static int syborg_serial_init(SysBusDevice *dev)
 
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_serial_readfn,
-                                       syborg_serial_writefn, s);
+                                       syborg_serial_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr) {
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 95e07d7bbf..cedcd8ed47 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -215,7 +215,8 @@ static int syborg_timer_init(SysBusDevice *dev)
     }
     sysbus_init_irq(dev, &s->irq);
     iomemtype = cpu_register_io_memory(syborg_timer_readfn,
-                                       syborg_timer_writefn, s);
+                                       syborg_timer_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
 
     bh = qemu_bh_new(syborg_timer_tick, s);
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 4dfd1a87b9..ee08c49105 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -265,7 +265,8 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
     proxy->vdev->nvectors = 0;
     sysbus_init_irq(&proxy->busdev, &proxy->irq);
     iomemtype = cpu_register_io_memory(syborg_virtio_readfn,
-                                       syborg_virtio_writefn, proxy);
+                                       syborg_virtio_writefn, proxy,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(&proxy->busdev, 0x1000, iomemtype);
 
     proxy->id = ((uint32_t)0x1af4 << 16) | vdev->device_id;
diff --git a/hw/sysbus.c b/hw/sysbus.c
index d817721420..1583bd8589 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -22,11 +22,13 @@
 #include "monitor.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static char *sysbus_get_fw_dev_path(DeviceState *dev);
 
 struct BusInfo system_bus_info = {
     .name       = "System",
     .size       = sizeof(BusState),
     .print_dev  = sysbus_dev_print,
+    .get_fw_dev_path = sysbus_get_fw_dev_path,
 };
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
@@ -106,6 +108,16 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
+void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
+{
+    pio_addr_t i;
+
+    for (i = 0; i < size; i++) {
+        assert(dev->num_pio < QDEV_MAX_PIO);
+        dev->pio[dev->num_pio++] = ioport++;
+    }
+}
+
 static int sysbus_device_init(DeviceState *dev, DeviceInfo *base)
 {
     SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev);
@@ -171,3 +183,21 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
                        indent, "", s->mmio[i].addr, s->mmio[i].size);
     }
 }
+
+static char *sysbus_get_fw_dev_path(DeviceState *dev)
+{
+    SysBusDevice *s = sysbus_from_qdev(dev);
+    char path[40];
+    int off;
+
+    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
+
+    if (s->num_mmio) {
+        snprintf(path + off, sizeof(path) - off, "@"TARGET_FMT_plx,
+                 s->mmio[0].addr);
+    } else if (s->num_pio) {
+        snprintf(path + off, sizeof(path) - off, "@i%04x", s->pio[0]);
+    }
+
+    return strdup(path);
+}
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 5980901845..e9eb618a72 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -6,6 +6,7 @@
 #include "qdev.h"
 
 #define QDEV_MAX_MMIO 32
+#define QDEV_MAX_PIO 32
 #define QDEV_MAX_IRQ 256
 
 typedef struct SysBusDevice SysBusDevice;
@@ -23,6 +24,8 @@ struct SysBusDevice {
         mmio_mapfunc cb;
         ram_addr_t iofunc;
     } mmio[QDEV_MAX_MMIO];
+    int num_pio;
+    pio_addr_t pio[QDEV_MAX_PIO];
 };
 
 typedef int (*sysbus_initfn)(SysBusDevice *dev);
@@ -45,6 +48,7 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
                             mmio_mapfunc cb);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
+void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
 
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 16db51dc2e..c3fbe4e205 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -590,7 +590,7 @@ TC6393xbState *tc6393xb_init(uint32_t base, qemu_irq irq)
     s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
 
     iomemtype = cpu_register_io_memory(tc6393xb_readfn,
-                    tc6393xb_writefn, s);
+                    tc6393xb_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(base, 0x10000, iomemtype);
 
     s->vram_addr = qemu_ram_alloc(NULL, "tc6393xb.vram", 0x100000);
diff --git a/hw/tcx.c b/hw/tcx.c
index 6ee65bb224..0e32830a87 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -522,12 +522,13 @@ static int tcx_init1(SysBusDevice *dev)
     vram_base += size;
 
     /* DAC */
-    io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s);
+    io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, TCX_DAC_NREGS, io_memory);
 
     /* TEC (dummy) */
     dummy_memory = cpu_register_io_memory(tcx_dummy_read, tcx_dummy_write,
-                                          s);
+                                          s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, TCX_TEC_NREGS, dummy_memory);
     /* THC: NetBSD writes here even with 8-bit display: dummy */
     sysbus_init_mmio(dev, TCX_THC_NREGS_24, dummy_memory);
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 4864be5e8d..0005e1cffb 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -740,7 +740,7 @@ TUSBState *tusb6010_init(qemu_irq intr)
     s->intr = 0x00000000;
     s->otg_timer_val = 0;
     s->iomemtype[1] = cpu_register_io_memory(tusb_async_readfn,
-                    tusb_async_writefn, s);
+                    tusb_async_writefn, s, DEVICE_NATIVE_ENDIAN);
     s->irq = intr;
     s->otg_timer = qemu_new_timer(vm_clock, tusb_otg_tick, s);
     s->pwr_timer = qemu_new_timer(vm_clock, tusb_power_tick, s);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 1310211aec..5f150589e1 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -121,7 +121,6 @@ static void unin_data_write(ReadWriteHandler *handler,
                             pcibus_t addr, uint32_t val, int len)
 {
     UNINState *s = container_of(handler, UNINState, data_handler);
-    val = qemu_bswap_len(val, len);
     UNIN_DPRINTF("write addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
     pci_data_write(s->host_state.bus,
                    unin_get_config_reg(s->host_state.config_reg, addr),
@@ -138,7 +137,6 @@ static uint32_t unin_data_read(ReadWriteHandler *handler,
                         unin_get_config_reg(s->host_state.config_reg, addr),
                         len);
     UNIN_DPRINTF("read addr %" FMT_PCIBUS " len %d val %x\n", addr, len, val);
-    val = qemu_bswap_len(val, len);
     return val;
 }
 
@@ -151,10 +149,12 @@ static int pci_unin_main_init_device(SysBusDevice *dev)
     /* Uninorth main bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
     s->data_handler.read = unin_data_read;
     s->data_handler.write = unin_data_write;
-    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler);
+    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
+                                                 DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
@@ -172,10 +172,12 @@ static int pci_u3_agp_init_device(SysBusDevice *dev)
     /* Uninorth U3 AGP bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
     s->data_handler.read = unin_data_read;
     s->data_handler.write = unin_data_write;
-    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler);
+    pci_mem_data = cpu_register_io_memory_simple(&s->data_handler,
+                                                 DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
 
@@ -194,8 +196,10 @@ static int pci_unin_agp_init_device(SysBusDevice *dev)
     /* Uninorth AGP bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 0);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
+    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
+                                               DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
@@ -209,8 +213,10 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     /* Uninorth internal bus */
     s = FROM_SYSBUS(UNINState, dev);
 
-    pci_mem_config = pci_host_conf_register_mmio(&s->host_state, 0);
-    pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
+    pci_mem_config = pci_host_conf_register_mmio(&s->host_state,
+                                                 DEVICE_LITTLE_ENDIAN);
+    pci_mem_data = pci_host_data_register_mmio(&s->host_state,
+                                               DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
     return 0;
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index b692503f54..8b4583c1e6 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -5,11 +5,13 @@
 #include "monitor.h"
 
 static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+static char *usbbus_get_fw_dev_path(DeviceState *dev);
 
 static struct BusInfo usb_bus_info = {
     .name      = "USB",
     .size      = sizeof(USBBus),
     .print_dev = usb_bus_dev_print,
+    .get_fw_dev_path = usbbus_get_fw_dev_path,
 };
 static int next_usb_bus = 0;
 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@@ -110,11 +112,12 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
 }
 
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       usb_attachfn attach)
+                       USBDevice *pdev, usb_attachfn attach)
 {
     port->opaque = opaque;
     port->index = index;
     port->attach = attach;
+    port->pdev = pdev;
     QTAILQ_INSERT_TAIL(&bus->free, port, next);
     bus->nfree++;
 }
@@ -306,3 +309,43 @@ USBDevice *usbdevice_create(const char *cmdline)
     }
     return usb->usbdevice_init(params);
 }
+
+static int usbbus_get_fw_dev_path_helper(USBDevice *d, USBBus *bus, char *p,
+                                         int len)
+{
+    int l = 0;
+    USBPort *port;
+
+    QTAILQ_FOREACH(port, &bus->used, next) {
+        if (port->dev == d) {
+            if (port->pdev) {
+                l = usbbus_get_fw_dev_path_helper(port->pdev, bus, p, len);
+            }
+            l += snprintf(p + l, len - l, "%s@%x/", qdev_fw_name(&d->qdev),
+                          port->index);
+            break;
+        }
+    }
+
+    return l;
+}
+
+static char *usbbus_get_fw_dev_path(DeviceState *dev)
+{
+    USBDevice *d = (USBDevice*)dev;
+    USBBus *bus = usb_bus_from_device(d);
+    char path[100];
+    int l;
+
+    assert(d->attached != 0);
+
+    l = usbbus_get_fw_dev_path_helper(d, bus, path, sizeof(path));
+
+    if (l == 0) {
+        abort();
+    }
+
+    path[l-1] = '\0';
+
+    return strdup(path);
+}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 2a1edfc956..8a3f829c96 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -535,7 +535,7 @@ static int usb_hub_initfn(USBDevice *dev)
     for (i = 0; i < s->nb_ports; i++) {
         port = &s->ports[i];
         usb_register_port(usb_bus_from_device(dev),
-                          &port->port, s, i, usb_hub_attach);
+                          &port->port, s, i, &s->dev, usb_hub_attach);
         port->wPortStatus = PORT_STAT_POWER;
         port->wPortChange = 0;
     }
@@ -545,6 +545,7 @@ static int usb_hub_initfn(USBDevice *dev)
 static struct USBDeviceInfo hub_info = {
     .product_desc   = "QEMU USB Hub",
     .qdev.name      = "usb-hub",
+    .qdev.fw_name    = "hub",
     .qdev.size      = sizeof(USBHubState),
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 7f15842962..9efe7a6344 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -343,7 +343,7 @@ struct MUSBState {
     }
 
     usb_bus_new(&s->bus, NULL /* FIXME */);
-    usb_register_port(&s->bus, &s->port, s, 0, musb_attach);
+    usb_register_port(&s->bus, &s->port, s, 0, NULL, musb_attach);
 
     return s;
 }
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 58c672f426..84924550fd 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -27,6 +27,7 @@
 #include "usb.h"
 #include "net.h"
 #include "qemu-queue.h"
+#include "sysemu.h"
 
 /*#define TRAFFIC_DEBUG*/
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -1463,6 +1464,7 @@ static int usb_net_initfn(USBDevice *dev)
              s->conf.macaddr.a[4],
              s->conf.macaddr.a[5]);
 
+    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
     return 0;
 }
 
@@ -1496,6 +1498,7 @@ static USBDevice *usb_net_init(const char *cmdline)
 static struct USBDeviceInfo net_info = {
     .product_desc   = "QEMU USB Network Interface",
     .qdev.name      = "usb-net",
+    .qdev.fw_name    = "network",
     .qdev.size      = sizeof(USBNetState),
     .init           = usb_net_initfn,
     .handle_packet  = usb_generic_handle_packet,
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 8fb2f83f0f..240e8409af 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1530,9 +1530,6 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
         }
     }
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    retval = bswap32(retval);
-#endif
     return retval;
 }
 
@@ -1542,10 +1539,6 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
 
     addr &= 0xff;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned write\n");
@@ -1697,7 +1690,8 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                 usb_frame_time, usb_bit_time);
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci);
+    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
+                                       DEVICE_LITTLE_ENDIAN);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1705,7 +1699,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
     usb_bus_new(&ohci->bus, dev);
     ohci->num_ports = num_ports;
     for (i = 0; i < num_ports; i++) {
-        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, ohci_attach);
+        usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, ohci_attach);
     }
 
     ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 1d834004b3..b9b822fcb1 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1115,7 +1115,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
 
     usb_bus_new(&s->bus, &s->dev.qdev);
     for(i = 0; i < NB_PORTS; i++) {
-        usb_register_port(&s->bus, &s->ports[i].port, s, i, uhci_attach);
+        usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, uhci_attach);
     }
     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
     s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.h b/hw/usb.h
index 00d2802206..0b32d77e6f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -203,6 +203,7 @@ struct USBPort {
     USBDevice *dev;
     usb_attachfn attach;
     void *opaque;
+    USBDevice *pdev;
     int index; /* internal port index, may be used with the opaque */
     QTAILQ_ENTRY(USBPort) next;
 };
@@ -312,7 +313,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
 USBDevice *usb_create_simple(USBBus *bus, const char *name);
 USBDevice *usbdevice_create(const char *cmdline);
 void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
-                       usb_attachfn attach);
+                       USBDevice *pdev, usb_attachfn attach);
 void usb_unregister_port(USBBus *bus, USBPort *port);
 int usb_device_attach(USBDevice *dev);
 int usb_device_detach(USBDevice *dev);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index a76bdfad61..2fed8a00fd 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -32,18 +32,12 @@ static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
 static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
     pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
 }
 
 static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
     pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
 }
 
@@ -58,9 +52,6 @@ static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr)
 {
     uint32_t val;
     val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap16(val);
-#endif
     return val;
 }
 
@@ -68,9 +59,6 @@ static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr)
 {
     uint32_t val;
     val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
     return val;
 }
 
@@ -108,11 +96,7 @@ static void pci_vpb_map(SysBusDevice *dev, target_phys_addr_t base)
 
     if (s->realview) {
         /* IO memory area.  */
-#ifdef TARGET_WORDS_BIGENDIAN
-        isa_mmio_init(base + 0x03000000, 0x00100000, 1);
-#else
-        isa_mmio_init(base + 0x03000000, 0x00100000, 0);
-#endif
+        isa_mmio_init(base + 0x03000000, 0x00100000);
     }
 }
 
@@ -132,7 +116,8 @@ static int pci_vpb_init(SysBusDevice *dev)
     /* ??? Register memory space.  */
 
     s->mem_config = cpu_register_io_memory(pci_vpb_config_read,
-                                           pci_vpb_config_write, bus);
+                                           pci_vpb_config_write, bus,
+                                           DEVICE_LITTLE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x04000000, pci_vpb_map);
 
     pci_create_simple(bus, -1, "versatile_pci_host");
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index c51ee02c4d..be758e447f 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -143,7 +143,8 @@ static int vpb_sic_init(SysBusDevice *dev)
     }
     s->irq = 31;
     iomemtype = cpu_register_io_memory(vpb_sic_readfn,
-                                       vpb_sic_writefn, s);
+                                       vpb_sic_writefn, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? Save/restore.  */
     return 0;
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 680b557a0b..4954bb18be 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -97,8 +97,10 @@ static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
     int s_ioport_ctrl, vga_io_memory;
 
     s->it_shift = it_shift;
-    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
+    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s,
+                                           DEVICE_NATIVE_ENDIAN);
+    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
 
     vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
diff --git a/hw/vga.c b/hw/vga.c
index c057f4f653..b5c8741d2b 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2320,7 +2320,8 @@ void vga_init(VGACommonState *s)
 #endif
 #endif /* CONFIG_BOCHS_VBE */
 
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
+    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
+                                           DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
                                  vga_io_memory);
     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
index cff5b07297..6b18842fd4 100644
--- a/hw/virtio-9p-debug.c
+++ b/hw/virtio-9p-debug.c
@@ -552,8 +552,8 @@ void pprint_pdu(V9fsPDU *pdu)
         break;
     case P9_TLINK:
         fprintf(llogfile, "TLINK: (");
-        pprint_int32(pdu, 0, &offset, "fid");
-        pprint_str(pdu, 0, &offset, ", oldpath");
+        pprint_int32(pdu, 0, &offset, "dfid");
+        pprint_int32(pdu, 0, &offset, ", fid");
         pprint_str(pdu, 0, &offset, ", newpath");
         break;
     case P9_RLINK:
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 0d520201b4..a8e7525bf6 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -480,9 +480,9 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
 }
 
 static int local_utimensat(FsContext *s, const char *path,
-		       const struct timespec *buf)
+                           const struct timespec *buf)
 {
-    return utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
+    return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
 }
 
 static int local_remove(FsContext *ctx, const char *path)
@@ -490,9 +490,13 @@ static int local_remove(FsContext *ctx, const char *path)
     return remove(rpath(ctx, path));
 }
 
-static int local_fsync(FsContext *ctx, int fd)
+static int local_fsync(FsContext *ctx, int fd, int datasync)
 {
-    return fsync(fd);
+    if (datasync) {
+        return qemu_fdatasync(fd);
+    } else {
+        return fsync(fd);
+    }
 }
 
 static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
diff --git a/hw/virtio-9p-xattr.c b/hw/virtio-9p-xattr.c
index 175f372c39..1aab081de2 100644
--- a/hw/virtio-9p-xattr.c
+++ b/hw/virtio-9p-xattr.c
@@ -73,6 +73,9 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
 
     /* Get the actual len */
     xattr_len = llistxattr(rpath(ctx, path), value, 0);
+    if (xattr_len <= 0) {
+        return xattr_len;
+    }
 
     /* Now fetch the xattr and find the actual size */
     orig_value = qemu_malloc(xattr_len);
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index daade77ed9..7c59988a51 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -248,9 +248,9 @@ static int v9fs_do_remove(V9fsState *s, V9fsString *path)
     return s->ops->remove(&s->ctx, path->data);
 }
 
-static int v9fs_do_fsync(V9fsState *s, int fd)
+static int v9fs_do_fsync(V9fsState *s, int fd, int datasync)
 {
-    return s->ops->fsync(&s->ctx, fd);
+    return s->ops->fsync(&s->ctx, fd, datasync);
 }
 
 static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
@@ -1868,16 +1868,17 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
     int32_t fid;
     size_t offset = 7;
     V9fsFidState *fidp;
+    int datasync;
     int err;
 
-    pdu_unmarshal(pdu, offset, "d", &fid);
+    pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
     fidp = lookup_fid(s, fid);
     if (fidp == NULL) {
         err = -ENOENT;
         v9fs_post_do_fsync(s, pdu, err);
         return;
     }
-    err = v9fs_do_fsync(s, fidp->fs.fd);
+    err = v9fs_do_fsync(s, fidp->fs.fd, datasync);
     v9fs_post_do_fsync(s, pdu, err);
 }
 
@@ -3001,7 +3002,7 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 
     /* do we need to sync the file? */
     if (donttouch_stat(&vs->v9stat)) {
-        err = v9fs_do_fsync(s, vs->fidp->fs.fd);
+        err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0);
         v9fs_wstat_post_fsync(s, vs, err);
         return;
     }
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index e5f9b2795a..f62ccd1fe8 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -548,6 +548,8 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     bdrv_set_removable(s->bs, 0);
     s->bs->buffer_alignment = conf->logical_block_size;
 
+    add_boot_device_path(conf->bootindex, dev, "/disk@0,0");
+
     return &s->vdev;
 }
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 1d61f191b6..ec1bf8dda7 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -99,9 +99,14 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
     }
 }
 
-static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
+static bool virtio_net_started(VirtIONet *n, uint8_t status)
+{
+    return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+        (n->status & VIRTIO_NET_S_LINK_UP) && n->vm_running;
+}
+
+static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
 {
-    VirtIONet *n = to_virtio_net(vdev);
     if (!n->nic->nc.peer) {
         return;
     }
@@ -112,9 +117,7 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
     if (!tap_get_vhost_net(n->nic->nc.peer)) {
         return;
     }
-    if (!!n->vhost_started == ((status & VIRTIO_CONFIG_S_DRIVER_OK) &&
-                               (n->status & VIRTIO_NET_S_LINK_UP) &&
-                               n->vm_running)) {
+    if (!!n->vhost_started == virtio_net_started(n, status)) {
         return;
     }
     if (!n->vhost_started) {
@@ -131,6 +134,32 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
     }
 }
 
+static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
+{
+    VirtIONet *n = to_virtio_net(vdev);
+
+    virtio_net_vhost_status(n, status);
+
+    if (!n->tx_waiting) {
+        return;
+    }
+
+    if (virtio_net_started(n, status) && !n->vhost_started) {
+        if (n->tx_timer) {
+            qemu_mod_timer(n->tx_timer,
+                           qemu_get_clock(vm_clock) + n->tx_timeout);
+        } else {
+            qemu_bh_schedule(n->tx_bh);
+        }
+    } else {
+        if (n->tx_timer) {
+            qemu_del_timer(n->tx_timer);
+        } else {
+            qemu_bh_cancel(n->tx_bh);
+        }
+    }
+}
+
 static void virtio_net_set_link_status(VLANClientState *nc)
 {
     VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
@@ -424,6 +453,9 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
 static int virtio_net_can_receive(VLANClientState *nc)
 {
     VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
+    if (!n->vm_running) {
+        return 0;
+    }
 
     if (!virtio_queue_ready(n->rx_vq) ||
         !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
@@ -672,11 +704,12 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
 {
     VirtQueueElement elem;
     int32_t num_packets = 0;
-
     if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return num_packets;
     }
 
+    assert(n->vm_running);
+
     if (n->async_tx.elem.out_num) {
         virtio_queue_set_notification(n->tx_vq, 0);
         return num_packets;
@@ -735,6 +768,12 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIONet *n = to_virtio_net(vdev);
 
+    /* This happens when device was stopped but VCPU wasn't. */
+    if (!n->vm_running) {
+        n->tx_waiting = 1;
+        return;
+    }
+
     if (n->tx_waiting) {
         virtio_queue_set_notification(vq, 1);
         qemu_del_timer(n->tx_timer);
@@ -755,14 +794,19 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
     if (unlikely(n->tx_waiting)) {
         return;
     }
+    n->tx_waiting = 1;
+    /* This happens when device was stopped but VCPU wasn't. */
+    if (!n->vm_running) {
+        return;
+    }
     virtio_queue_set_notification(vq, 0);
     qemu_bh_schedule(n->tx_bh);
-    n->tx_waiting = 1;
 }
 
 static void virtio_net_tx_timer(void *opaque)
 {
     VirtIONet *n = opaque;
+    assert(n->vm_running);
 
     n->tx_waiting = 0;
 
@@ -779,6 +823,8 @@ static void virtio_net_tx_bh(void *opaque)
     VirtIONet *n = opaque;
     int32_t ret;
 
+    assert(n->vm_running);
+
     n->tx_waiting = 0;
 
     /* Just in case the driver is not ready on more */
@@ -923,15 +969,6 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
         }
     }
     n->mac_table.first_multi = i;
-
-    if (n->tx_waiting) {
-        if (n->tx_timer) {
-            qemu_mod_timer(n->tx_timer,
-                           qemu_get_clock(vm_clock) + n->tx_timeout);
-        } else {
-            qemu_bh_schedule(n->tx_bh);
-        }
-    }
     return 0;
 }
 
@@ -1017,6 +1054,8 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
+    add_boot_device_path(conf->bootindex, dev, "/ethernet-phy@0");
+
     return &n->vdev;
 }
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c65765a273..6186142b2b 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -699,6 +699,7 @@ static int virtio_9p_init_pci(PCIDevice *pci_dev)
 static PCIDeviceInfo virtio_info[] = {
     {
         .qdev.name = "virtio-blk-pci",
+        .qdev.alias = "virtio-blk",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_blk_init_pci,
         .exit      = virtio_blk_exit_pci,
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index d0f4e1b5b5..d9dd52fc60 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1250,7 +1250,7 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
     s->vram_base = addr;
 #ifdef DIRECT_VRAM
     iomemtype = cpu_register_io_memory(vmsvga_vram_read,
-                    vmsvga_vram_write, s);
+                    vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
 #else
     iomemtype = s->vga.vram_offset | IO_MEM_RAM;
 #endif
diff --git a/hw/wdt_i6300esb.c b/hw/wdt_i6300esb.c
index 46e1df8b6f..90bf5f65a7 100644
--- a/hw/wdt_i6300esb.c
+++ b/hw/wdt_i6300esb.c
@@ -140,14 +140,27 @@ static void i6300esb_disable_timer(I6300State *d)
     qemu_del_timer(d->timer);
 }
 
-static void i6300esb_reset(I6300State *d)
+static void i6300esb_reset(DeviceState *dev)
 {
-    /* XXX We should probably reset other parts of the state here,
-     * but we should also reset our state on general machine reset
-     * too.  For now just disable the timer so it doesn't fire
-     * again after the reboot.
-     */
+    PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
+    I6300State *d = DO_UPCAST(I6300State, dev, pdev);
+
+    i6300esb_debug("I6300State = %p\n", d);
+
     i6300esb_disable_timer(d);
+
+    /* NB: Don't change d->previous_reboot_flag in this function. */
+
+    d->reboot_enabled = 1;
+    d->clock_scale = CLOCK_SCALE_1KHZ;
+    d->int_type = INT_TYPE_IRQ;
+    d->free_run = 0;
+    d->locked = 0;
+    d->enabled = 0;
+    d->timer1_preload = 0xfffff;
+    d->timer2_preload = 0xfffff;
+    d->stage = 1;
+    d->unlock_state = 0;
 }
 
 /* This function is called when the watchdog expires.  Note that
@@ -181,7 +194,7 @@ static void i6300esb_timer_expired(void *vp)
         if (d->reboot_enabled) {
             d->previous_reboot_flag = 1;
             watchdog_perform_action(); /* This reboots, exits, etc */
-            i6300esb_reset(d);
+            i6300esb_reset(&d->dev.qdev);
         }
 
         /* In "free running mode" we start stage 1 again. */
@@ -361,7 +374,8 @@ static void i6300esb_map(PCIDevice *dev, int region_num,
     i6300esb_debug("addr = %"FMT_PCIBUS", size = %"FMT_PCIBUS", type = %d\n",
                    addr, size, type);
 
-    io_mem = cpu_register_io_memory(mem_read, mem_write, d);
+    io_mem = cpu_register_io_memory(mem_read, mem_write, d,
+                                    DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory (addr, 0x10, io_mem);
     /* qemu_register_coalesced_mmio (addr, 0x10); ? */
 }
@@ -394,17 +408,9 @@ static int i6300esb_init(PCIDevice *dev)
     I6300State *d = DO_UPCAST(I6300State, dev, dev);
     uint8_t *pci_conf;
 
-    d->reboot_enabled = 1;
-    d->clock_scale = CLOCK_SCALE_1KHZ;
-    d->int_type = INT_TYPE_IRQ;
-    d->free_run = 0;
-    d->locked = 0;
-    d->enabled = 0;
+    i6300esb_debug("I6300State = %p\n", d);
+
     d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d);
-    d->timer1_preload = 0xfffff;
-    d->timer2_preload = 0xfffff;
-    d->stage = 1;
-    d->unlock_state = 0;
     d->previous_reboot_flag = 0;
 
     pci_conf = d->dev.config;
@@ -427,6 +433,7 @@ static PCIDeviceInfo i6300esb_info = {
     .qdev.name    = "i6300esb",
     .qdev.size    = sizeof(I6300State),
     .qdev.vmsd    = &vmstate_i6300esb,
+    .qdev.reset   = i6300esb_reset,
     .config_read  = i6300esb_config_read,
     .config_write = i6300esb_config_write,
     .init         = i6300esb_init,
diff --git a/hw/wdt_ib700.c b/hw/wdt_ib700.c
index c34687bcac..b6235ebe52 100644
--- a/hw/wdt_ib700.c
+++ b/hw/wdt_ib700.c
@@ -97,6 +97,8 @@ static int wdt_ib700_init(ISADevice *dev)
 {
     IB700State *s = DO_UPCAST(IB700State, dev, dev);
 
+    ib700_debug("watchdog init\n");
+
     s->timer = qemu_new_timer(vm_clock, ib700_timer_expired, s);
     register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, s);
     register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, s);
@@ -104,16 +106,26 @@ static int wdt_ib700_init(ISADevice *dev)
     return 0;
 }
 
+static void wdt_ib700_reset(DeviceState *dev)
+{
+    IB700State *s = DO_UPCAST(IB700State, dev.qdev, dev);
+
+    ib700_debug("watchdog reset\n");
+
+    qemu_del_timer(s->timer);
+}
+
 static WatchdogTimerModel model = {
     .wdt_name = "ib700",
     .wdt_description = "iBASE 700",
 };
 
 static ISADeviceInfo wdt_ib700_info = {
-    .qdev.name = "ib700",
-    .qdev.size = sizeof(IB700State),
-    .qdev.vmsd = &vmstate_ib700,
-    .init      = wdt_ib700_init,
+    .qdev.name  = "ib700",
+    .qdev.size  = sizeof(IB700State),
+    .qdev.vmsd  = &vmstate_ib700,
+    .qdev.reset = wdt_ib700_reset,
+    .init       = wdt_ib700_init,
 };
 
 static void wdt_ib700_register_devices(void)
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 37e33ec011..54b57d774f 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -224,7 +224,7 @@ static int xilinx_ethlite_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
     s->rxbuf = 0;
 
-    regs = cpu_register_io_memory(eth_read, eth_write, s);
+    regs = cpu_register_io_memory(eth_read, eth_write, s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4, regs);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 8ef6474fba..cb72d5a14e 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -153,7 +153,7 @@ static int xilinx_intc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
     sysbus_init_irq(dev, &p->parent_irq);
 
-    pic_regs = cpu_register_io_memory(pic_read, pic_write, p);
+    pic_regs = cpu_register_io_memory(pic_read, pic_write, p, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4, pic_regs);
     return 0;
 }
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index e2d9541cda..30827b03cd 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -210,7 +210,8 @@ static int xilinx_timer_init(SysBusDevice *dev)
         ptimer_set_freq(xt->ptimer, t->freq_hz);
     }
 
-    timer_regs = cpu_register_io_memory(timer_read, timer_write, t);
+    timer_regs = cpu_register_io_memory(timer_read, timer_write, t,
+                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs);
     return 0;
 }
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index adab759fdb..9b94e98fe3 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -201,7 +201,8 @@ static int xilinx_uartlite_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->irq);
 
     uart_update_status(s);
-    uart_regs = cpu_register_io_memory(uart_read, uart_write, s);
+    uart_regs = cpu_register_io_memory(uart_read, uart_write, s,
+                                       DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, R_MAX * 4, uart_regs);
 
     s->chr = qdev_init_chardev(&dev->qdev);
diff --git a/hw/zaurus.c b/hw/zaurus.c
index dd999d7d44..54ec3f00d5 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -228,7 +228,7 @@ ScoopInfo *scoop_init(PXA2xxState *cpu,
     s->status = 0x02;
     s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16);
     iomemtype = cpu_register_io_memory(scoop_readfn,
-                    scoop_writefn, s);
+                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
     cpu_register_physical_memory(target_base, 0x1000, iomemtype);
     register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
 
diff --git a/migration.c b/migration.c
index 622a9d2d95..e5ba51c314 100644
--- a/migration.c
+++ b/migration.c
@@ -370,8 +370,6 @@ void migrate_fd_put_ready(void *opaque)
         DPRINTF("done iterating\n");
         vm_stop(0);
 
-        qemu_aio_flush();
-        bdrv_flush_all();
         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
             if (old_vm_running) {
                 vm_start();
diff --git a/monitor.c b/monitor.c
index ec31eac8c1..aae81bb8ad 100644
--- a/monitor.c
+++ b/monitor.c
@@ -351,10 +351,8 @@ static void monitor_json_emitter(Monitor *mon, const QObject *data)
 {
     QString *json;
 
-    if (mon->flags & MONITOR_USE_PRETTY)
-	json = qobject_to_json_pretty(data);
-    else
-	json = qobject_to_json(data);
+    json = mon->flags & MONITOR_USE_PRETTY ? qobject_to_json_pretty(data) :
+                                             qobject_to_json(data);
     assert(json != NULL);
 
     qstring_append_chr(json, '\n');
@@ -1848,11 +1846,20 @@ static int do_system_powerdown(Monitor *mon, const QDict *qdict,
 }
 
 #if defined(TARGET_I386)
-static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
+static void print_pte(Monitor *mon, target_phys_addr_t addr,
+                      target_phys_addr_t pte,
+                      target_phys_addr_t mask)
 {
-    monitor_printf(mon, "%08x: %08x %c%c%c%c%c%c%c%c\n",
+#ifdef TARGET_X86_64
+    if (addr & (1ULL << 47)) {
+        addr |= -1LL << 48;
+    }
+#endif
+    monitor_printf(mon, TARGET_FMT_plx ": " TARGET_FMT_plx
+                   " %c%c%c%c%c%c%c%c%c\n",
                    addr,
                    pte & mask,
+                   pte & PG_NX_MASK ? 'X' : '-',
                    pte & PG_GLOBAL_MASK ? 'G' : '-',
                    pte & PG_PSE_MASK ? 'P' : '-',
                    pte & PG_DIRTY_MASK ? 'D' : '-',
@@ -1863,25 +1870,19 @@ static void print_pte(Monitor *mon, uint32_t addr, uint32_t pte, uint32_t mask)
                    pte & PG_RW_MASK ? 'W' : '-');
 }
 
-static void tlb_info(Monitor *mon)
+static void tlb_info_32(Monitor *mon, CPUState *env)
 {
-    CPUState *env;
     int l1, l2;
     uint32_t pgd, pde, pte;
 
-    env = mon_get_cpu();
-
-    if (!(env->cr[0] & CR0_PG_MASK)) {
-        monitor_printf(mon, "PG disabled\n");
-        return;
-    }
     pgd = env->cr[3] & ~0xfff;
     for(l1 = 0; l1 < 1024; l1++) {
         cpu_physical_memory_read(pgd + l1 * 4, (uint8_t *)&pde, 4);
         pde = le32_to_cpu(pde);
         if (pde & PG_PRESENT_MASK) {
             if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
-                print_pte(mon, (l1 << 22), pde, ~((1 << 20) - 1));
+                /* 4M pages */
+                print_pte(mon, (l1 << 22), pde, ~((1 << 21) - 1));
             } else {
                 for(l2 = 0; l2 < 1024; l2++) {
                     cpu_physical_memory_read((pde & ~0xfff) + l2 * 4,
@@ -1898,14 +1899,142 @@ static void tlb_info(Monitor *mon)
     }
 }
 
-static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
-                      uint32_t end, int prot)
+static void tlb_info_pae32(Monitor *mon, CPUState *env)
+{
+    int l1, l2, l3;
+    uint64_t pdpe, pde, pte;
+    uint64_t pdp_addr, pd_addr, pt_addr;
+
+    pdp_addr = env->cr[3] & ~0x1f;
+    for (l1 = 0; l1 < 4; l1++) {
+        cpu_physical_memory_read(pdp_addr + l1 * 8, (uint8_t *)&pdpe, 8);
+        pdpe = le64_to_cpu(pdpe);
+        if (pdpe & PG_PRESENT_MASK) {
+            pd_addr = pdpe & 0x3fffffffff000ULL;
+            for (l2 = 0; l2 < 512; l2++) {
+                cpu_physical_memory_read(pd_addr + l2 * 8,
+                                         (uint8_t *)&pde, 8);
+                pde = le64_to_cpu(pde);
+                if (pde & PG_PRESENT_MASK) {
+                    if (pde & PG_PSE_MASK) {
+                        /* 2M pages with PAE, CR4.PSE is ignored */
+                        print_pte(mon, (l1 << 30 ) + (l2 << 21), pde,
+                                  ~((target_phys_addr_t)(1 << 20) - 1));
+                    } else {
+                        pt_addr = pde & 0x3fffffffff000ULL;
+                        for (l3 = 0; l3 < 512; l3++) {
+                            cpu_physical_memory_read(pt_addr + l3 * 8,
+                                                     (uint8_t *)&pte, 8);
+                            pte = le64_to_cpu(pte);
+                            if (pte & PG_PRESENT_MASK) {
+                                print_pte(mon, (l1 << 30 ) + (l2 << 21)
+                                          + (l3 << 12),
+                                          pte & ~PG_PSE_MASK,
+                                          ~(target_phys_addr_t)0xfff);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+#ifdef TARGET_X86_64
+static void tlb_info_64(Monitor *mon, CPUState *env)
+{
+    uint64_t l1, l2, l3, l4;
+    uint64_t pml4e, pdpe, pde, pte;
+    uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr;
+
+    pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+    for (l1 = 0; l1 < 512; l1++) {
+        cpu_physical_memory_read(pml4_addr + l1 * 8, (uint8_t *)&pml4e, 8);
+        pml4e = le64_to_cpu(pml4e);
+        if (pml4e & PG_PRESENT_MASK) {
+            pdp_addr = pml4e & 0x3fffffffff000ULL;
+            for (l2 = 0; l2 < 512; l2++) {
+                cpu_physical_memory_read(pdp_addr + l2 * 8, (uint8_t *)&pdpe,
+                                         8);
+                pdpe = le64_to_cpu(pdpe);
+                if (pdpe & PG_PRESENT_MASK) {
+                    if (pdpe & PG_PSE_MASK) {
+                        /* 1G pages, CR4.PSE is ignored */
+                        print_pte(mon, (l1 << 39) + (l2 << 30), pdpe,
+                                  0x3ffffc0000000ULL);
+                    } else {
+                        pd_addr = pdpe & 0x3fffffffff000ULL;
+                        for (l3 = 0; l3 < 512; l3++) {
+                            cpu_physical_memory_read(pd_addr + l3 * 8,
+                                                     (uint8_t *)&pde, 8);
+                            pde = le64_to_cpu(pde);
+                            if (pde & PG_PRESENT_MASK) {
+                                if (pde & PG_PSE_MASK) {
+                                    /* 2M pages, CR4.PSE is ignored */
+                                    print_pte(mon, (l1 << 39) + (l2 << 30) +
+                                              (l3 << 21), pde,
+                                              0x3ffffffe00000ULL);
+                                } else {
+                                    pt_addr = pde & 0x3fffffffff000ULL;
+                                    for (l4 = 0; l4 < 512; l4++) {
+                                        cpu_physical_memory_read(pt_addr
+                                                                 + l4 * 8,
+                                                                 (uint8_t *)&pte,
+                                                                 8);
+                                        pte = le64_to_cpu(pte);
+                                        if (pte & PG_PRESENT_MASK) {
+                                            print_pte(mon, (l1 << 39) +
+                                                      (l2 << 30) +
+                                                      (l3 << 21) + (l4 << 12),
+                                                      pte & ~PG_PSE_MASK,
+                                                      0x3fffffffff000ULL);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
+static void tlb_info(Monitor *mon)
+{
+    CPUState *env;
+
+    env = mon_get_cpu();
+
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        monitor_printf(mon, "PG disabled\n");
+        return;
+    }
+    if (env->cr[4] & CR4_PAE_MASK) {
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_LMA_MASK) {
+            tlb_info_64(mon, env);
+        } else
+#endif
+        {
+            tlb_info_pae32(mon, env);
+        }
+    } else {
+        tlb_info_32(mon, env);
+    }
+}
+
+static void mem_print(Monitor *mon, target_phys_addr_t *pstart,
+                      int *plast_prot,
+                      target_phys_addr_t end, int prot)
 {
     int prot1;
     prot1 = *plast_prot;
     if (prot != prot1) {
         if (*pstart != -1) {
-            monitor_printf(mon, "%08x-%08x %08x %c%c%c\n",
+            monitor_printf(mon, TARGET_FMT_plx "-" TARGET_FMT_plx " "
+                           TARGET_FMT_plx " %c%c%c\n",
                            *pstart, end, end - *pstart,
                            prot1 & PG_USER_MASK ? 'u' : '-',
                            'r',
@@ -1919,18 +2048,12 @@ static void mem_print(Monitor *mon, uint32_t *pstart, int *plast_prot,
     }
 }
 
-static void mem_info(Monitor *mon)
+static void mem_info_32(Monitor *mon, CPUState *env)
 {
-    CPUState *env;
     int l1, l2, prot, last_prot;
-    uint32_t pgd, pde, pte, start, end;
-
-    env = mon_get_cpu();
+    uint32_t pgd, pde, pte;
+    target_phys_addr_t start, end;
 
-    if (!(env->cr[0] & CR0_PG_MASK)) {
-        monitor_printf(mon, "PG disabled\n");
-        return;
-    }
     pgd = env->cr[3] & ~0xfff;
     last_prot = 0;
     start = -1;
@@ -1962,6 +2085,162 @@ static void mem_info(Monitor *mon)
         }
     }
 }
+
+static void mem_info_pae32(Monitor *mon, CPUState *env)
+{
+    int l1, l2, l3, prot, last_prot;
+    uint64_t pdpe, pde, pte;
+    uint64_t pdp_addr, pd_addr, pt_addr;
+    target_phys_addr_t start, end;
+
+    pdp_addr = env->cr[3] & ~0x1f;
+    last_prot = 0;
+    start = -1;
+    for (l1 = 0; l1 < 4; l1++) {
+        cpu_physical_memory_read(pdp_addr + l1 * 8, (uint8_t *)&pdpe, 8);
+        pdpe = le64_to_cpu(pdpe);
+        end = l1 << 30;
+        if (pdpe & PG_PRESENT_MASK) {
+            pd_addr = pdpe & 0x3fffffffff000ULL;
+            for (l2 = 0; l2 < 512; l2++) {
+                cpu_physical_memory_read(pd_addr + l2 * 8,
+                                         (uint8_t *)&pde, 8);
+                pde = le64_to_cpu(pde);
+                end = (l1 << 30) + (l2 << 21);
+                if (pde & PG_PRESENT_MASK) {
+                    if (pde & PG_PSE_MASK) {
+                        prot = pde & (PG_USER_MASK | PG_RW_MASK |
+                                      PG_PRESENT_MASK);
+                        mem_print(mon, &start, &last_prot, end, prot);
+                    } else {
+                        pt_addr = pde & 0x3fffffffff000ULL;
+                        for (l3 = 0; l3 < 512; l3++) {
+                            cpu_physical_memory_read(pt_addr + l3 * 8,
+                                                     (uint8_t *)&pte, 8);
+                            pte = le64_to_cpu(pte);
+                            end = (l1 << 30) + (l2 << 21) + (l3 << 12);
+                            if (pte & PG_PRESENT_MASK) {
+                                prot = pte & (PG_USER_MASK | PG_RW_MASK |
+                                              PG_PRESENT_MASK);
+                            } else {
+                                prot = 0;
+                            }
+                            mem_print(mon, &start, &last_prot, end, prot);
+                        }
+                    }
+                } else {
+                    prot = 0;
+                    mem_print(mon, &start, &last_prot, end, prot);
+                }
+            }
+        } else {
+            prot = 0;
+            mem_print(mon, &start, &last_prot, end, prot);
+        }
+    }
+}
+
+
+#ifdef TARGET_X86_64
+static void mem_info_64(Monitor *mon, CPUState *env)
+{
+    int prot, last_prot;
+    uint64_t l1, l2, l3, l4;
+    uint64_t pml4e, pdpe, pde, pte;
+    uint64_t pml4_addr, pdp_addr, pd_addr, pt_addr, start, end;
+
+    pml4_addr = env->cr[3] & 0x3fffffffff000ULL;
+    last_prot = 0;
+    start = -1;
+    for (l1 = 0; l1 < 512; l1++) {
+        cpu_physical_memory_read(pml4_addr + l1 * 8, (uint8_t *)&pml4e, 8);
+        pml4e = le64_to_cpu(pml4e);
+        end = l1 << 39;
+        if (pml4e & PG_PRESENT_MASK) {
+            pdp_addr = pml4e & 0x3fffffffff000ULL;
+            for (l2 = 0; l2 < 512; l2++) {
+                cpu_physical_memory_read(pdp_addr + l2 * 8, (uint8_t *)&pdpe,
+                                         8);
+                pdpe = le64_to_cpu(pdpe);
+                end = (l1 << 39) + (l2 << 30);
+                if (pdpe & PG_PRESENT_MASK) {
+                    if (pdpe & PG_PSE_MASK) {
+                        prot = pde & (PG_USER_MASK | PG_RW_MASK |
+                                      PG_PRESENT_MASK);
+                        mem_print(mon, &start, &last_prot, end, prot);
+                    } else {
+                        pd_addr = pdpe & 0x3fffffffff000ULL;
+                        for (l3 = 0; l3 < 512; l3++) {
+                            cpu_physical_memory_read(pd_addr + l3 * 8,
+                                                     (uint8_t *)&pde, 8);
+                            pde = le64_to_cpu(pde);
+                            end = (l1 << 39) + (l2 << 30) + (l3 << 21);
+                            if (pde & PG_PRESENT_MASK) {
+                                if (pde & PG_PSE_MASK) {
+                                    prot = pde & (PG_USER_MASK | PG_RW_MASK |
+                                                  PG_PRESENT_MASK);
+                                    mem_print(mon, &start, &last_prot, end, prot);
+                                } else {
+                                    pt_addr = pde & 0x3fffffffff000ULL;
+                                    for (l4 = 0; l4 < 512; l4++) {
+                                        cpu_physical_memory_read(pt_addr
+                                                                 + l4 * 8,
+                                                                 (uint8_t *)&pte,
+                                                                 8);
+                                        pte = le64_to_cpu(pte);
+                                        end = (l1 << 39) + (l2 << 30) +
+                                            (l3 << 21) + (l4 << 12);
+                                        if (pte & PG_PRESENT_MASK) {
+                                            prot = pte & (PG_USER_MASK | PG_RW_MASK |
+                                                          PG_PRESENT_MASK);
+                                        } else {
+                                            prot = 0;
+                                        }
+                                        mem_print(mon, &start, &last_prot, end, prot);
+                                    }
+                                }
+                            } else {
+                                prot = 0;
+                                mem_print(mon, &start, &last_prot, end, prot);
+                            }
+                        }
+                    }
+                } else {
+                    prot = 0;
+                    mem_print(mon, &start, &last_prot, end, prot);
+                }
+            }
+        } else {
+            prot = 0;
+            mem_print(mon, &start, &last_prot, end, prot);
+        }
+    }
+}
+#endif
+
+static void mem_info(Monitor *mon)
+{
+    CPUState *env;
+
+    env = mon_get_cpu();
+
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        monitor_printf(mon, "PG disabled\n");
+        return;
+    }
+    if (env->cr[4] & CR4_PAE_MASK) {
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_LMA_MASK) {
+            mem_info_64(mon, env);
+        } else
+#endif
+        {
+            mem_info_pae32(mon, env);
+        }
+    } else {
+        mem_info_32(mon, env);
+    }
+}
 #endif
 
 #if defined(TARGET_SH4)
@@ -3891,49 +4170,43 @@ void monitor_set_error(Monitor *mon, QError *qerror)
 
 static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
 {
-    if (monitor_ctrl_mode(mon)) {
-        if (ret && !monitor_has_error(mon)) {
-            /*
-             * If it returns failure, it must have passed on error.
-             *
-             * Action: Report an internal error to the client if in QMP.
-             */
-            qerror_report(QERR_UNDEFINED_ERROR);
-            MON_DEBUG("command '%s' returned failure but did not pass an error\n",
-                      cmd->name);
-        }
+    if (ret && !monitor_has_error(mon)) {
+        /*
+         * If it returns failure, it must have passed on error.
+         *
+         * Action: Report an internal error to the client if in QMP.
+         */
+        qerror_report(QERR_UNDEFINED_ERROR);
+        MON_DEBUG("command '%s' returned failure but did not pass an error\n",
+                  cmd->name);
+    }
 
 #ifdef CONFIG_DEBUG_MONITOR
-        if (!ret && monitor_has_error(mon)) {
-            /*
-             * If it returns success, it must not have passed an error.
-             *
-             * Action: Report the passed error to the client.
-             */
-            MON_DEBUG("command '%s' returned success but passed an error\n",
-                      cmd->name);
-        }
-
-        if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
-            /*
-             * Handlers should not call Monitor print functions.
-             *
-             * Action: Ignore them in QMP.
-             *
-             * (XXX: we don't check any 'info' or 'query' command here
-             * because the user print function _is_ called by do_info(), hence
-             * we will trigger this check. This problem will go away when we
-             * make 'query' commands real and kill do_info())
-             */
-            MON_DEBUG("command '%s' called print functions %d time(s)\n",
-                      cmd->name, mon_print_count_get(mon));
-        }
-#endif
-    } else {
-        assert(!monitor_has_error(mon));
-        QDECREF(mon->error);
-        mon->error = NULL;
+    if (!ret && monitor_has_error(mon)) {
+        /*
+         * If it returns success, it must not have passed an error.
+         *
+         * Action: Report the passed error to the client.
+         */
+        MON_DEBUG("command '%s' returned success but passed an error\n",
+                  cmd->name);
+    }
+
+    if (mon_print_count_get(mon) > 0 && strcmp(cmd->name, "info") != 0) {
+        /*
+         * Handlers should not call Monitor print functions.
+         *
+         * Action: Ignore them in QMP.
+         *
+         * (XXX: we don't check any 'info' or 'query' command here
+         * because the user print function _is_ called by do_info(), hence
+         * we will trigger this check. This problem will go away when we
+         * make 'query' commands real and kill do_info())
+         */
+        MON_DEBUG("command '%s' called print functions %d time(s)\n",
+                  cmd->name, mon_print_count_get(mon));
     }
+#endif
 }
 
 static void handle_user_command(Monitor *mon, const char *cmdline)
@@ -4464,10 +4737,8 @@ static void qmp_call_query_cmd(Monitor *mon, const mon_cmd_t *cmd)
         }
     } else {
         cmd->mhandler.info_new(mon, &ret_data);
-        if (ret_data) {
-            monitor_protocol_emitter(mon, ret_data);
-            qobject_decref(ret_data);
-        }
+        monitor_protocol_emitter(mon, ret_data);
+        qobject_decref(ret_data);
     }
 }
 
diff --git a/net.c b/net.c
index c5e6063fcf..9ba5be22dd 100644
--- a/net.c
+++ b/net.c
@@ -1050,6 +1050,10 @@ static const struct {
                 .name = "mcast",
                 .type = QEMU_OPT_STRING,
                 .help = "UDP multicast address and port number",
+            }, {
+                .name = "localaddr",
+                .type = QEMU_OPT_STRING,
+                .help = "source address for multicast packets",
             },
             { /* end of list */ }
         },
diff --git a/net.h b/net.h
index 44c31a9b32..6ceca50fc3 100644
--- a/net.h
+++ b/net.h
@@ -17,12 +17,14 @@ typedef struct NICConf {
     MACAddr macaddr;
     VLANState *vlan;
     VLANClientState *peer;
+    int32_t bootindex;
 } NICConf;
 
 #define DEFINE_NIC_PROPERTIES(_state, _conf)                            \
     DEFINE_PROP_MACADDR("mac",   _state, _conf.macaddr),                \
     DEFINE_PROP_VLAN("vlan",     _state, _conf.vlan),                   \
-    DEFINE_PROP_NETDEV("netdev", _state, _conf.peer)
+    DEFINE_PROP_NETDEV("netdev", _state, _conf.peer),                   \
+    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)
 
 /* VLANs support */
 
diff --git a/net/socket.c b/net/socket.c
index 1c4e153e3f..916c2a8e10 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -149,7 +149,7 @@ static void net_socket_send_dgram(void *opaque)
     qemu_send_packet(&s->nc, s->buf, size);
 }
 
-static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
+static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
 {
     struct ip_mreq imr;
     int fd;
@@ -183,7 +183,11 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
 
     /* Add host to multicast group */
     imr.imr_multiaddr = mcastaddr->sin_addr;
-    imr.imr_interface.s_addr = htonl(INADDR_ANY);
+    if (localaddr) {
+        imr.imr_interface = *localaddr;
+    } else {
+        imr.imr_interface.s_addr = htonl(INADDR_ANY);
+    }
 
     ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                      (const char *)&imr, sizeof(struct ip_mreq));
@@ -201,6 +205,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
 	goto fail;
     }
 
+    /* If a bind address is given, only send packets from that address */
+    if (localaddr != NULL) {
+        ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, localaddr, sizeof(*localaddr));
+        if (ret < 0) {
+            perror("setsockopt(IP_MULTICAST_IF)");
+            goto fail;
+        }
+    }
+
     socket_set_nonblock(fd);
     return fd;
 fail:
@@ -248,7 +261,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
 		return NULL;
 	    }
 	    /* clone dgram socket */
-	    newfd = net_socket_mcast_create(&saddr);
+	    newfd = net_socket_mcast_create(&saddr, NULL);
 	    if (newfd < 0) {
 		/* error already reported by net_socket_mcast_create() */
 		close(fd);
@@ -468,17 +481,26 @@ static int net_socket_connect_init(VLANState *vlan,
 static int net_socket_mcast_init(VLANState *vlan,
                                  const char *model,
                                  const char *name,
-                                 const char *host_str)
+                                 const char *host_str,
+                                 const char *localaddr_str)
 {
     NetSocketState *s;
     int fd;
     struct sockaddr_in saddr;
+    struct in_addr localaddr, *param_localaddr;
 
     if (parse_host_port(&saddr, host_str) < 0)
         return -1;
 
+    if (localaddr_str != NULL) {
+        if (inet_aton(localaddr_str, &localaddr) == 0)
+            return -1;
+        param_localaddr = &localaddr;
+    } else {
+        param_localaddr = NULL;
+    }
 
-    fd = net_socket_mcast_create(&saddr);
+    fd = net_socket_mcast_create(&saddr, param_localaddr);
     if (fd < 0)
 	return -1;
 
@@ -505,8 +527,9 @@ int net_init_socket(QemuOpts *opts,
 
         if (qemu_opt_get(opts, "listen") ||
             qemu_opt_get(opts, "connect") ||
-            qemu_opt_get(opts, "mcast")) {
-            error_report("listen=, connect= and mcast= is invalid with fd=");
+            qemu_opt_get(opts, "mcast") ||
+            qemu_opt_get(opts, "localaddr")) {
+            error_report("listen=, connect=, mcast= and localaddr= is invalid with fd=\n");
             return -1;
         }
 
@@ -524,8 +547,9 @@ int net_init_socket(QemuOpts *opts,
 
         if (qemu_opt_get(opts, "fd") ||
             qemu_opt_get(opts, "connect") ||
-            qemu_opt_get(opts, "mcast")) {
-            error_report("fd=, connect= and mcast= is invalid with listen=");
+            qemu_opt_get(opts, "mcast") ||
+            qemu_opt_get(opts, "localaddr")) {
+            error_report("fd=, connect=, mcast= and localaddr= is invalid with listen=\n");
             return -1;
         }
 
@@ -539,8 +563,9 @@ int net_init_socket(QemuOpts *opts,
 
         if (qemu_opt_get(opts, "fd") ||
             qemu_opt_get(opts, "listen") ||
-            qemu_opt_get(opts, "mcast")) {
-            error_report("fd=, listen= and mcast= is invalid with connect=");
+            qemu_opt_get(opts, "mcast") ||
+            qemu_opt_get(opts, "localaddr")) {
+            error_report("fd=, listen=, mcast= and localaddr= is invalid with connect=\n");
             return -1;
         }
 
@@ -550,7 +575,7 @@ int net_init_socket(QemuOpts *opts,
             return -1;
         }
     } else if (qemu_opt_get(opts, "mcast")) {
-        const char *mcast;
+        const char *mcast, *localaddr;
 
         if (qemu_opt_get(opts, "fd") ||
             qemu_opt_get(opts, "connect") ||
@@ -560,8 +585,9 @@ int net_init_socket(QemuOpts *opts,
         }
 
         mcast = qemu_opt_get(opts, "mcast");
+        localaddr = qemu_opt_get(opts, "localaddr");
 
-        if (net_socket_mcast_init(vlan, "socket", name, mcast) == -1) {
+        if (net_socket_mcast_init(vlan, "socket", name, mcast, localaddr) == -1) {
             return -1;
         }
     } else {
diff --git a/oslib-posix.c b/oslib-posix.c
index 6e9b0c3c13..7bc5f7cf09 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -107,3 +107,51 @@ int qemu_pipe(int pipefd[2])
 
     return ret;
 }
+
+int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
+                   int flags)
+{
+    struct timeval tv[2], tv_now;
+    struct stat st;
+    int i;
+#ifdef CONFIG_UTIMENSAT
+    int ret;
+
+    ret = utimensat(dirfd, path, times, flags);
+    if (ret != -1 || errno != ENOSYS) {
+        return ret;
+    }
+#endif
+    /* Fallback: use utimes() instead of utimensat() */
+
+    /* happy if special cases */
+    if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
+        return 0;
+    }
+    if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
+        return utimes(path, NULL);
+    }
+
+    /* prepare for hard cases */
+    if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
+        gettimeofday(&tv_now, NULL);
+    }
+    if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
+        stat(path, &st);
+    }
+
+    for (i = 0; i < 2; i++) {
+        if (times[i].tv_nsec == UTIME_NOW) {
+            tv[i].tv_sec = tv_now.tv_sec;
+            tv[i].tv_usec = tv_now.tv_usec;
+        } else if (times[i].tv_nsec == UTIME_OMIT) {
+            tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
+            tv[i].tv_usec = 0;
+        } else {
+            tv[i].tv_sec = times[i].tv_sec;
+            tv[i].tv_usec = times[i].tv_nsec / 1000;
+        }
+    }
+
+    return utimes(path, &tv[0]);
+}
diff --git a/qemu-config.c b/qemu-config.c
index 52f18bef31..965fa46fdf 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -429,6 +429,22 @@ QemuOptsList qemu_spice_opts = {
     },
 };
 
+QemuOptsList qemu_option_rom_opts = {
+    .name = "option-rom",
+    .implied_opt_name = "romfile",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
+    .desc = {
+        {
+            .name = "bootindex",
+            .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "romfile",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end if list */ }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -442,6 +458,7 @@ static QemuOptsList *vm_config_groups[32] = {
 #ifdef CONFIG_SIMPLE_TRACE
     &qemu_trace_opts,
 #endif
+    &qemu_option_rom_opts,
     NULL,
 };
 
diff --git a/qemu-img.c b/qemu-img.c
index fa77ac0dbe..52282e3add 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -188,6 +188,33 @@ static int read_password(char *buf, int buf_size)
 }
 #endif
 
+static int print_block_option_help(const char *filename, const char *fmt)
+{
+    BlockDriver *drv, *proto_drv;
+    QEMUOptionParameter *create_options = NULL;
+
+    /* Find driver and parse its options */
+    drv = bdrv_find_format(fmt);
+    if (!drv) {
+        error("Unknown file format '%s'", fmt);
+        return 1;
+    }
+
+    proto_drv = bdrv_find_protocol(filename);
+    if (!proto_drv) {
+        error("Unknown protocol '%s'", filename);
+        return 1;
+    }
+
+    create_options = append_option_parameters(create_options,
+                                              drv->create_options);
+    create_options = append_option_parameters(create_options,
+                                              proto_drv->create_options);
+    print_option_help(create_options);
+    free_option_parameters(create_options);
+    return 0;
+}
+
 static BlockDriverState *bdrv_new_open(const char *filename,
                                        const char *fmt,
                                        int flags)
@@ -234,21 +261,9 @@ fail:
 }
 
 static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
-    int flags, const char *base_filename, const char *base_fmt)
+                                 const char *base_filename,
+                                 const char *base_fmt)
 {
-    if (flags & BLOCK_FLAG_ENCRYPT) {
-        if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
-            error("Encryption not supported for file format '%s'", fmt);
-            return -1;
-        }
-    }
-    if (flags & BLOCK_FLAG_COMPAT6) {
-        if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
-            error("VMDK version 6 not supported for file format '%s'", fmt);
-            return -1;
-        }
-    }
-
     if (base_filename) {
         if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
             error("Backing file not supported for file format '%s'", fmt);
@@ -266,21 +281,23 @@ static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
 
 static int img_create(int argc, char **argv)
 {
-    int c, ret = 0, flags;
+    int c, ret = 0;
     const char *fmt = "raw";
     const char *base_fmt = NULL;
     const char *filename;
     const char *base_filename = NULL;
     BlockDriver *drv, *proto_drv;
     QEMUOptionParameter *param = NULL, *create_options = NULL;
+    QEMUOptionParameter *backing_fmt = NULL;
     char *options = NULL;
 
-    flags = 0;
     for(;;) {
         c = getopt(argc, argv, "F:b:f:he6o:");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -294,11 +311,13 @@ static int img_create(int argc, char **argv)
             fmt = optarg;
             break;
         case 'e':
-            flags |= BLOCK_FLAG_ENCRYPT;
-            break;
+            error("qemu-img: option -e is deprecated, please use \'-o "
+                  "encryption\' instead!");
+            return 1;
         case '6':
-            flags |= BLOCK_FLAG_COMPAT6;
-            break;
+            error("qemu-img: option -6 is deprecated, please use \'-o "
+                  "compat6\' instead!");
+            return 1;
         case 'o':
             options = optarg;
             break;
@@ -306,21 +325,29 @@ static int img_create(int argc, char **argv)
     }
 
     /* Get the filename */
-    if (optind >= argc)
+    if (optind >= argc) {
         help();
+    }
     filename = argv[optind++];
 
+    if (options && !strcmp(options, "?")) {
+        ret = print_block_option_help(filename, fmt);
+        goto out;
+    }
+
     /* Find driver and parse its options */
     drv = bdrv_find_format(fmt);
     if (!drv) {
         error("Unknown file format '%s'", fmt);
-        return 1;
+        ret = -1;
+        goto out;
     }
 
     proto_drv = bdrv_find_protocol(filename);
     if (!proto_drv) {
         error("Unknown protocol '%s'", filename);
-        return 1;
+        ret = -1;
+        goto out;
     }
 
     create_options = append_option_parameters(create_options,
@@ -328,11 +355,6 @@ static int img_create(int argc, char **argv)
     create_options = append_option_parameters(create_options,
                                               proto_drv->create_options);
 
-    if (options && !strcmp(options, "?")) {
-        print_option_help(create_options);
-        goto out;
-    }
-
     /* Create parameter list with default values */
     param = parse_option_parameters("", create_options, param);
     set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
@@ -353,19 +375,27 @@ static int img_create(int argc, char **argv)
     }
 
     /* Add old-style options to parameters */
-    ret = add_old_style_options(fmt, param, flags, base_filename, base_fmt);
+    ret = add_old_style_options(fmt, param, base_filename, base_fmt);
     if (ret < 0) {
         goto out;
     }
 
+    backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
+    if (backing_fmt && backing_fmt->value.s) {
+        if (!bdrv_find_format(backing_fmt->value.s)) {
+            error("Unknown backing file format '%s'",
+                  backing_fmt->value.s);
+            ret = -1;
+            goto out;
+        }
+    }
+
     // The size for the image must always be specified, with one exception:
     // If we are using a backing file, we can obtain the size from there
     if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
 
         QEMUOptionParameter *backing_file =
             get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
-        QEMUOptionParameter *backing_fmt =
-            get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
 
         if (backing_file && backing_file->value.s) {
             BlockDriverState *bs;
@@ -374,14 +404,7 @@ static int img_create(int argc, char **argv)
             char buf[32];
 
             if (backing_fmt && backing_fmt->value.s) {
-                 if (bdrv_find_format(backing_fmt->value.s)) {
-                     fmt = backing_fmt->value.s;
-                } else {
-                     error("Unknown backing file format '%s'",
-                        backing_fmt->value.s);
-                     ret = -1;
-                     goto out;
-                }
+                fmt = backing_fmt->value.s;
             }
 
             bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS);
@@ -407,8 +430,6 @@ static int img_create(int argc, char **argv)
     puts("");
 
     ret = bdrv_create(drv, filename, param);
-    free_option_parameters(create_options);
-    free_option_parameters(param);
 
     if (ret < 0) {
         if (ret == -ENOTSUP) {
@@ -420,6 +441,8 @@ static int img_create(int argc, char **argv)
         }
     }
 out:
+    free_option_parameters(create_options);
+    free_option_parameters(param);
     if (ret) {
         return 1;
     }
@@ -444,9 +467,11 @@ static int img_check(int argc, char **argv)
     fmt = NULL;
     for(;;) {
         c = getopt(argc, argv, "f:h");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -455,8 +480,9 @@ static int img_check(int argc, char **argv)
             break;
         }
     }
-    if (optind >= argc)
+    if (optind >= argc) {
         help();
+    }
     filename = argv[optind++];
 
     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
@@ -520,9 +546,11 @@ static int img_commit(int argc, char **argv)
     fmt = NULL;
     for(;;) {
         c = getopt(argc, argv, "f:h");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -531,8 +559,9 @@ static int img_commit(int argc, char **argv)
             break;
         }
     }
-    if (optind >= argc)
+    if (optind >= argc) {
         help();
+    }
     filename = argv[optind++];
 
     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
@@ -636,7 +665,7 @@ static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
 
 static int img_convert(int argc, char **argv)
 {
-    int c, ret = 0, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
+    int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
     const char *fmt, *out_fmt, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
     BlockDriverState **bs = NULL, *out_bs = NULL;
@@ -653,12 +682,14 @@ static int img_convert(int argc, char **argv)
     fmt = NULL;
     out_fmt = "raw";
     out_baseimg = NULL;
-    flags = 0;
+    compress = 0;
     for(;;) {
         c = getopt(argc, argv, "f:O:B:s:hce6o:");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -672,14 +703,16 @@ static int img_convert(int argc, char **argv)
             out_baseimg = optarg;
             break;
         case 'c':
-            flags |= BLOCK_FLAG_COMPRESS;
+            compress = 1;
             break;
         case 'e':
-            flags |= BLOCK_FLAG_ENCRYPT;
-            break;
+            error("qemu-img: option -e is deprecated, please use \'-o "
+                  "encryption\' instead!");
+            return 1;
         case '6':
-            flags |= BLOCK_FLAG_COMPAT6;
-            break;
+            error("qemu-img: option -6 is deprecated, please use \'-o "
+                  "compat6\' instead!");
+            return 1;
         case 'o':
             options = optarg;
             break;
@@ -690,20 +723,24 @@ static int img_convert(int argc, char **argv)
     }
 
     bs_n = argc - optind - 1;
-    if (bs_n < 1) help();
+    if (bs_n < 1) {
+        help();
+    }
 
     out_filename = argv[argc - 1];
 
+    if (options && !strcmp(options, "?")) {
+        ret = print_block_option_help(out_filename, out_fmt);
+        goto out;
+    }
+
     if (bs_n > 1 && out_baseimg) {
         error("-B makes no sense when concatenating multiple input images");
-        return 1;
+        ret = -1;
+        goto out;
     }
         
-    bs = calloc(bs_n, sizeof(BlockDriverState *));
-    if (!bs) {
-        error("Out of memory");
-        return 1;
-    }
+    bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
 
     total_sectors = 0;
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
@@ -749,10 +786,6 @@ static int img_convert(int argc, char **argv)
                                               drv->create_options);
     create_options = append_option_parameters(create_options,
                                               proto_drv->create_options);
-    if (options && !strcmp(options, "?")) {
-        print_option_help(create_options);
-        goto out;
-    }
 
     if (options) {
         param = parse_option_parameters(options, create_options, param);
@@ -766,7 +799,7 @@ static int img_convert(int argc, char **argv)
     }
 
     set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
-    ret = add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
+    ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
     if (ret < 0) {
         goto out;
     }
@@ -778,7 +811,7 @@ static int img_convert(int argc, char **argv)
     }
 
     /* Check if compression is supported */
-    if (flags & BLOCK_FLAG_COMPRESS) {
+    if (compress) {
         QEMUOptionParameter *encryption =
             get_option_parameter(param, BLOCK_OPT_ENCRYPT);
 
@@ -820,7 +853,7 @@ static int img_convert(int argc, char **argv)
     bdrv_get_geometry(bs[0], &bs_sectors);
     buf = qemu_malloc(IO_BUF_SIZE);
 
-    if (flags & BLOCK_FLAG_COMPRESS) {
+    if (compress) {
         ret = bdrv_get_info(out_bs, &bdi);
         if (ret < 0) {
             error("could not get block driver info");
@@ -880,8 +913,9 @@ static int img_convert(int argc, char **argv)
             }
             assert (remainder == 0);
 
-            if (n < cluster_sectors)
+            if (n < cluster_sectors) {
                 memset(buf + n * 512, 0, cluster_size - n * 512);
+            }
             if (is_not_zero(buf, cluster_size)) {
                 ret = bdrv_write_compressed(out_bs, sector_num, buf,
                                             cluster_sectors);
@@ -901,12 +935,14 @@ static int img_convert(int argc, char **argv)
         sector_num = 0; // total number of sectors converted so far
         for(;;) {
             nb_sectors = total_sectors - sector_num;
-            if (nb_sectors <= 0)
+            if (nb_sectors <= 0) {
                 break;
-            if (nb_sectors >= (IO_BUF_SIZE / 512))
+            }
+            if (nb_sectors >= (IO_BUF_SIZE / 512)) {
                 n = (IO_BUF_SIZE / 512);
-            else
+            } else {
                 n = nb_sectors;
+            }
 
             while (sector_num - bs_offset >= bs_sectors) {
                 bs_i ++;
@@ -918,8 +954,9 @@ static int img_convert(int argc, char **argv)
                    sector_num, bs_i, bs_offset, bs_sectors); */
             }
 
-            if (n > bs_offset + bs_sectors - sector_num)
+            if (n > bs_offset + bs_sectors - sector_num) {
                 n = bs_offset + bs_sectors - sector_num;
+            }
 
             if (has_zero_init) {
                 /* If the output image is being created as a copy on write image,
@@ -978,12 +1015,14 @@ out:
     if (out_bs) {
         bdrv_delete(out_bs);
     }
-    for (bs_i = 0; bs_i < bs_n; bs_i++) {
-        if (bs[bs_i]) {
-            bdrv_delete(bs[bs_i]);
+    if (bs) {
+        for (bs_i = 0; bs_i < bs_n; bs_i++) {
+            if (bs[bs_i]) {
+                bdrv_delete(bs[bs_i]);
+            }
         }
+        qemu_free(bs);
     }
-    free(bs);
     if (ret) {
         return 1;
     }
@@ -1053,9 +1092,11 @@ static int img_info(int argc, char **argv)
     fmt = NULL;
     for(;;) {
         c = getopt(argc, argv, "f:h");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -1064,8 +1105,9 @@ static int img_info(int argc, char **argv)
             break;
         }
     }
-    if (optind >= argc)
+    if (optind >= argc) {
         help();
+    }
     filename = argv[optind++];
 
     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
@@ -1076,11 +1118,12 @@ static int img_info(int argc, char **argv)
     bdrv_get_geometry(bs, &total_sectors);
     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
     allocated_size = get_allocated_file_size(filename);
-    if (allocated_size < 0)
+    if (allocated_size < 0) {
         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
-    else
+    } else {
         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
                                 allocated_size);
+    }
     printf("image: %s\n"
            "file format: %s\n"
            "virtual size: %s (%" PRId64 " bytes)\n"
@@ -1088,11 +1131,13 @@ static int img_info(int argc, char **argv)
            filename, fmt_name, size_buf,
            (total_sectors * 512),
            dsize_buf);
-    if (bdrv_is_encrypted(bs))
+    if (bdrv_is_encrypted(bs)) {
         printf("encrypted: yes\n");
+    }
     if (bdrv_get_info(bs, &bdi) >= 0) {
-        if (bdi.cluster_size != 0)
+        if (bdi.cluster_size != 0) {
             printf("cluster_size: %d\n", bdi.cluster_size);
+        }
     }
     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
     if (backing_filename[0] != '\0') {
@@ -1125,9 +1170,11 @@ static int img_snapshot(int argc, char **argv)
     /* Parse commandline parameters */
     for(;;) {
         c = getopt(argc, argv, "la:c:d:h");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             return 0;
@@ -1166,8 +1213,9 @@ static int img_snapshot(int argc, char **argv)
         }
     }
 
-    if (optind >= argc)
+    if (optind >= argc) {
         help();
+    }
     filename = argv[optind++];
 
     /* Open the image */
@@ -1191,23 +1239,26 @@ static int img_snapshot(int argc, char **argv)
         sn.date_nsec = tv.tv_usec * 1000;
 
         ret = bdrv_snapshot_create(bs, &sn);
-        if (ret)
+        if (ret) {
             error("Could not create snapshot '%s': %d (%s)",
                 snapshot_name, ret, strerror(-ret));
+        }
         break;
 
     case SNAPSHOT_APPLY:
         ret = bdrv_snapshot_goto(bs, snapshot_name);
-        if (ret)
+        if (ret) {
             error("Could not apply snapshot '%s': %d (%s)",
                 snapshot_name, ret, strerror(-ret));
+        }
         break;
 
     case SNAPSHOT_DELETE:
         ret = bdrv_snapshot_delete(bs, snapshot_name);
-        if (ret)
+        if (ret) {
             error("Could not delete snapshot '%s': %d (%s)",
                 snapshot_name, ret, strerror(-ret));
+        }
         break;
     }
 
@@ -1235,9 +1286,11 @@ static int img_rebase(int argc, char **argv)
 
     for(;;) {
         c = getopt(argc, argv, "uhf:F:b:");
-        if (c == -1)
+        if (c == -1) {
             break;
+        }
         switch(c) {
+        case '?':
         case 'h':
             help();
             return 0;
@@ -1256,8 +1309,9 @@ static int img_rebase(int argc, char **argv)
         }
     }
 
-    if ((optind >= argc) || !out_baseimg)
+    if ((optind >= argc) || !out_baseimg) {
         help();
+    }
     filename = argv[optind++];
 
     /*
@@ -1433,7 +1487,7 @@ static int img_resize(int argc, char **argv)
     int c, ret, relative;
     const char *filename, *fmt, *size;
     int64_t n, total_size;
-    BlockDriverState *bs;
+    BlockDriverState *bs = NULL;
     QEMUOptionParameter *param;
     QEMUOptionParameter resize_options[] = {
         {
@@ -1451,6 +1505,7 @@ static int img_resize(int argc, char **argv)
             break;
         }
         switch(c) {
+        case '?':
         case 'h':
             help();
             break;
@@ -1484,14 +1539,16 @@ static int img_resize(int argc, char **argv)
     param = parse_option_parameters("", resize_options, NULL);
     if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
         /* Error message already printed when size parsing fails */
-        exit(1);
+        ret = -1;
+        goto out;
     }
     n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
     free_option_parameters(param);
 
     bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
     if (!bs) {
-        return 1;
+        ret = -1;
+        goto out;
     }
 
     if (relative) {
@@ -1521,7 +1578,9 @@ static int img_resize(int argc, char **argv)
         break;
     }
 out:
-    bdrv_delete(bs);
+    if (bs) {
+        bdrv_delete(bs);
+    }
     if (ret) {
         return 1;
     }
diff --git a/qemu-malloc.c b/qemu-malloc.c
index 28fb05a481..b9b38514ac 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -64,10 +64,13 @@ void *qemu_realloc(void *ptr, size_t size)
 
 void *qemu_mallocz(size_t size)
 {
+    void *ptr;
     if (!size && !allow_zero_malloc()) {
         abort();
     }
-    return qemu_oom_check(calloc(1, size ? size : 1));
+    ptr = qemu_oom_check(calloc(1, size ? size : 1));
+    trace_qemu_malloc(size, ptr);
+    return ptr;
 }
 
 char *qemu_strdup(const char *str)
diff --git a/qemu-option.c b/qemu-option.c
index 1f8f41ae7d..65db54292b 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -394,8 +394,8 @@ QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
 /*
  * Parses a parameter string (param) into an option list (dest).
  *
- * list is the templace is. If dest is NULL, a new copy of list is created for
- * it. If list is NULL, this function fails.
+ * list is the template option list. If dest is NULL, a new copy of list is
+ * created. If list is NULL, this function fails.
  *
  * A parameter string consists of one or more parameters, separated by commas.
  * Each parameter consists of its name and possibly of a value. In the latter
@@ -416,20 +416,13 @@ QEMUOptionParameter *parse_option_parameters(const char *param,
     char value[256];
     char *param_delim, *value_delim;
     char next_delim;
-    size_t num_options;
 
     if (list == NULL) {
         return NULL;
     }
 
     if (dest == NULL) {
-        // Count valid options
-        num_options = count_option_parameters(list);
-
-        // Create a copy of the option list to fill in values
-        dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
-        allocated = dest;
-        memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
+        dest = allocated = append_option_parameters(NULL, list);
     }
 
     while (*param) {
diff --git a/qemu-options.hx b/qemu-options.hx
index 4d99a58fc5..accd16a55c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1061,8 +1061,9 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
 #endif
     "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
     "                connect the vlan 'n' to another VLAN using a socket connection\n"
-    "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n"
+    "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port[,localaddr=addr]]\n"
     "                connect the vlan 'n' to multicast maddr and port\n"
+    "                use 'localaddr=addr' to specify the host address to send packets from\n"
 #ifdef CONFIG_VDE
     "-net vde[,vlan=n][,name=str][,sock=socketpath][,port=n][,group=groupname][,mode=octalmode]\n"
     "                connect the vlan 'n' to port 'n' of a vde switch running\n"
@@ -1256,7 +1257,7 @@ qemu linux.img -net nic,macaddr=52:54:00:12:34:57 \
                -net socket,connect=127.0.0.1:1234
 @end example
 
-@item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}] [,mcast=@var{maddr}:@var{port}]
+@item -net socket[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,mcast=@var{maddr}:@var{port}[,localaddr=@var{addr}]]
 
 Create a VLAN @var{n} shared with another QEMU virtual
 machines using a UDP multicast socket, effectively making a bus for
@@ -1296,6 +1297,12 @@ qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \
 /path/to/linux ubd0=/path/to/root_fs eth0=mcast
 @end example
 
+Example (send packets from host's 1.2.3.4):
+@example
+qemu linux.img -net nic,macaddr=52:54:00:12:34:56 \
+               -net socket,mcast=239.192.168.1:1102,localaddr=1.2.3.4
+@end example
+
 @item -net vde[,vlan=@var{n}][,name=@var{name}][,sock=@var{socketpath}] [,port=@var{n}][,group=@var{groupname}][,mode=@var{octalmode}]
 Connect VLAN @var{n} to PORT @var{n} of a vde switch running on host and
 listening for incoming connections on @var{socketpath}. Use GROUP @var{groupname}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 353f87813f..81fd9ab389 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -39,4 +39,16 @@ void os_setup_post(void);
 typedef struct timeval qemu_timeval;
 #define qemu_gettimeofday(tp) gettimeofday(tp, NULL)
 
+#ifndef CONFIG_UTIMENSAT
+#ifndef UTIME_NOW
+# define UTIME_NOW     ((1l << 30) - 1l)
+#endif
+#ifndef UTIME_OMIT
+# define UTIME_OMIT    ((1l << 30) - 2l)
+#endif
+#endif
+typedef struct timespec qemu_timespec;
+int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
+    int flags);
+
 #endif
diff --git a/qmp-commands.hx b/qmp-commands.hx
index e5f157fe10..3486223517 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -495,7 +495,7 @@ EQMP
 
     {
         .name       = "migrate_set_speed",
-        .args_type  = "value:f",
+        .args_type  = "value:o",
         .params     = "value",
         .help       = "set maximum speed (in bytes) for migrations",
         .user_print = monitor_user_noop,
diff --git a/rwhandler.c b/rwhandler.c
index 1f9b6db4bc..bb2238ff1e 100644
--- a/rwhandler.c
+++ b/rwhandler.c
@@ -35,14 +35,14 @@ static CPUReadMemoryFunc * const cpu_io_memory_simple_read[] = {
     &cpu_io_memory_simple_readl,
 };
 
-int cpu_register_io_memory_simple(struct ReadWriteHandler *handler)
+int cpu_register_io_memory_simple(struct ReadWriteHandler *handler, int endian)
 {
     if (!handler->read || !handler->write) {
         return -1;
     }
     return cpu_register_io_memory(cpu_io_memory_simple_read,
                                   cpu_io_memory_simple_write,
-                                  handler);
+                                  handler, endian);
 }
 
 RWHANDLER_WRITE(ioport_simple_writeb, 1, uint32_t);
diff --git a/rwhandler.h b/rwhandler.h
index bc11849572..b2a5790548 100644
--- a/rwhandler.h
+++ b/rwhandler.h
@@ -19,7 +19,7 @@ struct ReadWriteHandler {
 
 /* Helpers for when we want to use a single routine with length. */
 /* CPU memory handler: both read and write must be present. */
-int cpu_register_io_memory_simple(ReadWriteHandler *);
+int cpu_register_io_memory_simple(ReadWriteHandler *, int endian);
 /* io port handler: can supply only read or write handlers. */
 int register_ioport_simple(ReadWriteHandler *,
                            pio_addr_t start, int length, int size);
diff --git a/savevm.c b/savevm.c
index d38f79e6bd..90aa237c9c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1575,8 +1575,6 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
     saved_vm_running = vm_running;
     vm_stop(0);
 
-    bdrv_flush_all();
-
     ret = qemu_savevm_state_begin(mon, f, 0, 0);
     if (ret < 0)
         goto out;
@@ -1885,8 +1883,6 @@ void do_savevm(Monitor *mon, const QDict *qdict)
         monitor_printf(mon, "No block device can accept snapshots\n");
         return;
     }
-    /* ??? Should this occur after vm_stop?  */
-    qemu_aio_flush();
 
     saved_vm_running = vm_running;
     vm_stop(0);
diff --git a/sysemu.h b/sysemu.h
index b81a70ec3e..38a20a3b04 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -60,6 +60,8 @@ void qemu_system_reset(void);
 void qemu_add_exit_notifier(Notifier *notify);
 void qemu_remove_exit_notifier(Notifier *notify);
 
+void qemu_add_machine_init_done_notifier(Notifier *notify);
+
 void do_savevm(Monitor *mon, const QDict *qdict);
 int load_vmstate(const char *name);
 void do_delvm(Monitor *mon, const QDict *qdict);
@@ -139,7 +141,11 @@ extern uint64_t node_mem[MAX_NODES];
 extern uint64_t node_cpumask[MAX_NODES];
 
 #define MAX_OPTION_ROMS 16
-extern const char *option_rom[MAX_OPTION_ROMS];
+typedef struct QEMUOptionRom {
+    const char *name;
+    int32_t bootindex;
+} QEMUOptionRom;
+extern QEMUOptionRom option_rom[MAX_OPTION_ROMS];
 extern int nb_option_roms;
 
 #define MAX_PROM_ENVS 128
@@ -188,4 +194,7 @@ void rtc_change_mon_event(struct tm *tm);
 
 void register_devices(void);
 
+void add_boot_device_path(int32_t bootindex, DeviceState *dev,
+                          const char *suffix);
+char *get_boot_devices_list(uint32_t *size);
 #endif
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5cacef7b58..5caa07cba8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -132,7 +132,7 @@ int kvm_arch_get_registers(CPUState *env)
 {
     struct kvm_regs regs;
     struct kvm_sregs sregs;
-    uint32_t i, ret;
+    int i, ret;
 
     ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
     if (ret < 0)
diff --git a/vl.c b/vl.c
index 2cd263eda4..c4d3fc0d3d 100644
--- a/vl.c
+++ b/vl.c
@@ -218,7 +218,7 @@ int cursor_hide = 1;
 int graphic_rotate = 0;
 uint8_t irq0override = 1;
 const char *watchdog;
-const char *option_rom[MAX_OPTION_ROMS];
+QEMUOptionRom option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
 int semihosting_enabled = 0;
 int old_param = 0;
@@ -229,6 +229,17 @@ unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
 
+typedef struct FWBootEntry FWBootEntry;
+
+struct FWBootEntry {
+    QTAILQ_ENTRY(FWBootEntry) link;
+    int32_t bootindex;
+    DeviceState *dev;
+    char *suffix;
+};
+
+QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+
 int nb_numa_nodes;
 uint64_t node_mem[MAX_NODES];
 uint64_t node_cpumask[MAX_NODES];
@@ -243,6 +254,9 @@ static void *boot_set_opaque;
 static NotifierList exit_notifiers =
     NOTIFIER_LIST_INITIALIZER(exit_notifiers);
 
+static NotifierList machine_init_done_notifiers =
+    NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
+
 int kvm_allowed = 0;
 uint32_t xen_domid;
 enum xen_mode xen_mode = XEN_EMULATE;
@@ -693,6 +707,83 @@ static void restore_boot_devices(void *opaque)
     qemu_free(standard_boot_devices);
 }
 
+void add_boot_device_path(int32_t bootindex, DeviceState *dev,
+                          const char *suffix)
+{
+    FWBootEntry *node, *i;
+
+    if (bootindex < 0) {
+        return;
+    }
+
+    assert(dev != NULL || suffix != NULL);
+
+    node = qemu_mallocz(sizeof(FWBootEntry));
+    node->bootindex = bootindex;
+    node->suffix = strdup(suffix);
+    node->dev = dev;
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        if (i->bootindex == bootindex) {
+            fprintf(stderr, "Two devices with same boot index %d\n", bootindex);
+            exit(1);
+        } else if (i->bootindex < bootindex) {
+            continue;
+        }
+        QTAILQ_INSERT_BEFORE(i, node, link);
+        return;
+    }
+    QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
+}
+
+/*
+ * This function returns null terminated string that consist of new line
+ * separated device pathes.
+ *
+ * memory pointed by "size" is assigned total length of the array in bytes
+ *
+ */
+char *get_boot_devices_list(uint32_t *size)
+{
+    FWBootEntry *i;
+    uint32_t total = 0;
+    char *list = NULL;
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        char *devpath = NULL, *bootpath;
+        int len;
+
+        if (i->dev) {
+            devpath = qdev_get_fw_dev_path(i->dev);
+            assert(devpath);
+        }
+
+        if (i->suffix && devpath) {
+            bootpath = qemu_malloc(strlen(devpath) + strlen(i->suffix) + 1);
+            sprintf(bootpath, "%s%s", devpath, i->suffix);
+            qemu_free(devpath);
+        } else if (devpath) {
+            bootpath = devpath;
+        } else {
+            bootpath = strdup(i->suffix);
+            assert(bootpath);
+        }
+
+        if (total) {
+            list[total-1] = '\n';
+        }
+        len = strlen(bootpath) + 1;
+        list = qemu_realloc(list, total + len);
+        memcpy(&list[total], bootpath, len);
+        total += len;
+        qemu_free(bootpath);
+    }
+
+    *size = total;
+
+    return list;
+}
+
 static void numa_add(const char *optarg)
 {
     char option[128];
@@ -1742,6 +1833,16 @@ static void qemu_run_exit_notifiers(void)
     notifier_list_notify(&exit_notifiers);
 }
 
+void qemu_add_machine_init_done_notifier(Notifier *notify)
+{
+    notifier_list_add(&machine_init_done_notifiers, notify);
+}
+
+static void qemu_run_machine_init_done_notifiers(void)
+{
+    notifier_list_notify(&machine_init_done_notifiers);
+}
+
 static const QEMUOption *lookup_opt(int argc, char **argv,
                                     const char **poptarg, int *poptind)
 {
@@ -2480,7 +2581,14 @@ int main(int argc, char **argv, char **envp)
 		    fprintf(stderr, "Too many option ROMs\n");
 		    exit(1);
 		}
-		option_rom[nb_option_roms] = optarg;
+                opts = qemu_opts_parse(qemu_find_opts("option-rom"), optarg, 1);
+                option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile");
+                option_rom[nb_option_roms].bootindex =
+                    qemu_opt_get_number(opts, "bootindex", -1);
+                if (!option_rom[nb_option_roms].name) {
+                    fprintf(stderr, "Option ROM file is not specified\n");
+                    exit(1);
+                }
 		nb_option_roms++;
 		break;
             case QEMU_OPTION_semihosting:
@@ -2981,6 +3089,8 @@ int main(int argc, char **argv, char **envp)
     }
 
     qemu_register_reset((void *)qbus_reset_all, sysbus_get_default());
+    qemu_run_machine_init_done_notifiers();
+
     qemu_system_reset();
     if (loadvm) {
         if (load_vmstate(loadvm) < 0) {