]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Merge remote-tracking branch 'remotes/kraxel/tags/pull-bootindex-20141015-1' into...
authorPeter Maydell <peter.maydell@linaro.org>
Wed, 15 Oct 2014 20:03:28 +0000 (21:03 +0100)
committerPeter Maydell <peter.maydell@linaro.org>
Thu, 16 Oct 2014 08:24:45 +0000 (09:24 +0100)
allow changing bootorder via monitor at runtime,
by making bootindex a writable qom property.

* remotes/kraxel/tags/pull-bootindex-20141015-1: (34 commits)
  bootindex: change fprintf to error_report
  bootindex: delete bootindex when device is removed
  bootindex: move calling add_boot_device_patch to bootindex setter function
  ide: add calling add_boot_device_patch in bootindex setter function
  nvma: ide: add bootindex to qom property
  usb-storage: add bootindex to qom property
  virtio-blk: alias bootindex property explicitly for virt-blk-pci/ccw/s390
  block: remove bootindex property from qdev to qom
  virtio-blk: add bootindex to qom property
  ide: add bootindex to qom property
  scsi: add bootindex to qom property
  isa-fdc: remove bootindexA/B property from qdev to qom
  redirect: remove bootindex property from qdev to qom
  vfio: remove bootindex property from qdev to qom
  pci-assign: remove bootindex property from qdev to qom
  host-libusb: remove bootindex property from qdev to qom
  virtio-net: alias bootindex property explicitly for virt-net-pci/ccw/s390
  net: remove bootindex property from qdev to qom
  usb-net: add bootindex to qom property
  vmxnet3: add bootindex to qom property
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
36 files changed:
Makefile.target
bootdevice.c [new file with mode: 0644]
hw/block/fdc.c
hw/block/nvme.c
hw/block/virtio-blk.c
hw/i386/kvm/pci-assign.c
hw/ide/qdev.c
hw/misc/vfio.c
hw/net/e1000.c
hw/net/eepro100.c
hw/net/lance.c
hw/net/ne2000-isa.c
hw/net/ne2000.c
hw/net/pcnet-pci.c
hw/net/pcnet.c
hw/net/pcnet.h
hw/net/rtl8139.c
hw/net/spapr_llan.c
hw/net/virtio-net.c
hw/net/vmxnet3.c
hw/nvram/fw_cfg.c
hw/s390x/s390-virtio-bus.c
hw/s390x/virtio-ccw.c
hw/scsi/scsi-bus.c
hw/scsi/scsi-disk.c
hw/scsi/scsi-generic.c
hw/usb/dev-network.c
hw/usb/dev-storage.c
hw/usb/host-libusb.c
hw/usb/redirect.c
hw/virtio/virtio-pci.c
include/hw/block/block.h
include/hw/nvram/fw_cfg.h
include/net/net.h
include/sysemu/sysemu.h
vl.c

index 1e8d7abcb3feff84e827d10fe3e65a4357db33ab..e9ff1eed7b9bcf74444af8000d86f56d286517dd 100644 (file)
@@ -127,7 +127,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
-obj-y += qtest.o
+obj-y += qtest.o bootdevice.o
 obj-y += hw/
 obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
diff --git a/bootdevice.c b/bootdevice.c
new file mode 100644 (file)
index 0000000..b29970c
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * QEMU Boot Device Implement
+ *
+ * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysemu/sysemu.h"
+#include "qapi/visitor.h"
+#include "qemu/error-report.h"
+
+typedef struct FWBootEntry FWBootEntry;
+
+struct FWBootEntry {
+    QTAILQ_ENTRY(FWBootEntry) link;
+    int32_t bootindex;
+    DeviceState *dev;
+    char *suffix;
+};
+
+static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
+    QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+
+void check_boot_index(int32_t bootindex, Error **errp)
+{
+    FWBootEntry *i;
+
+    if (bootindex >= 0) {
+        QTAILQ_FOREACH(i, &fw_boot_order, link) {
+            if (i->bootindex == bootindex) {
+                error_setg(errp, "The bootindex %d has already been used",
+                           bootindex);
+                return;
+            }
+        }
+    }
+}
+
+void del_boot_device_path(DeviceState *dev, const char *suffix)
+{
+    FWBootEntry *i;
+
+    if (dev == NULL) {
+        return;
+    }
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        if ((!suffix || !g_strcmp0(i->suffix, suffix)) &&
+             i->dev == dev) {
+            QTAILQ_REMOVE(&fw_boot_order, i, link);
+            g_free(i->suffix);
+            g_free(i);
+
+            break;
+        }
+    }
+}
+
+void add_boot_device_path(int32_t bootindex, DeviceState *dev,
+                          const char *suffix)
+{
+    FWBootEntry *node, *i;
+
+    if (bootindex < 0) {
+        del_boot_device_path(dev, suffix);
+        return;
+    }
+
+    assert(dev != NULL || suffix != NULL);
+
+    del_boot_device_path(dev, suffix);
+
+    node = g_malloc0(sizeof(FWBootEntry));
+    node->bootindex = bootindex;
+    node->suffix = g_strdup(suffix);
+    node->dev = dev;
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        if (i->bootindex == bootindex) {
+            error_report("Two devices with same boot index %d", bootindex);
+            exit(1);
+        } else if (i->bootindex < bootindex) {
+            continue;
+        }
+        QTAILQ_INSERT_BEFORE(i, node, link);
+        return;
+    }
+    QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
+}
+
+DeviceState *get_boot_device(uint32_t position)
+{
+    uint32_t counter = 0;
+    FWBootEntry *i = NULL;
+    DeviceState *res = NULL;
+
+    if (!QTAILQ_EMPTY(&fw_boot_order)) {
+        QTAILQ_FOREACH(i, &fw_boot_order, link) {
+            if (counter == position) {
+                res = i->dev;
+                break;
+            }
+            counter++;
+        }
+    }
+    return res;
+}
+
+/*
+ * This function returns null terminated string that consist of new line
+ * separated device paths.
+ *
+ * memory pointed by "size" is assigned total length of the array in bytes
+ *
+ */
+char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
+{
+    FWBootEntry *i;
+    size_t total = 0;
+    char *list = NULL;
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        char *devpath = NULL, *bootpath;
+        size_t len;
+
+        if (i->dev) {
+            devpath = qdev_get_fw_dev_path(i->dev);
+            assert(devpath);
+        }
+
+        if (i->suffix && !ignore_suffixes && devpath) {
+            size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
+
+            bootpath = g_malloc(bootpathlen);
+            snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
+            g_free(devpath);
+        } else if (devpath) {
+            bootpath = devpath;
+        } else if (!ignore_suffixes) {
+            assert(i->suffix);
+            bootpath = g_strdup(i->suffix);
+        } else {
+            bootpath = g_strdup("");
+        }
+
+        if (total) {
+            list[total-1] = '\n';
+        }
+        len = strlen(bootpath) + 1;
+        list = g_realloc(list, total + len);
+        memcpy(&list[total], bootpath, len);
+        total += len;
+        g_free(bootpath);
+    }
+
+    *size = total;
+
+    if (boot_strict && *size > 0) {
+        list[total-1] = '\n';
+        list = g_realloc(list, total + 5);
+        memcpy(&list[total], "HALT", 5);
+        *size = total + 5;
+    }
+    return list;
+}
+
+typedef struct {
+    int32_t *bootindex;
+    const char *suffix;
+    DeviceState *dev;
+} BootIndexProperty;
+
+static void device_get_bootindex(Object *obj, Visitor *v, void *opaque,
+                                 const char *name, Error **errp)
+{
+    BootIndexProperty *prop = opaque;
+    visit_type_int32(v, prop->bootindex, name, errp);
+}
+
+static void device_set_bootindex(Object *obj, Visitor *v, void *opaque,
+                                 const char *name, Error **errp)
+{
+    BootIndexProperty *prop = opaque;
+    int32_t boot_index;
+    Error *local_err = NULL;
+
+    visit_type_int32(v, &boot_index, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* check whether bootindex is present in fw_boot_order list  */
+    check_boot_index(boot_index, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* change bootindex to a new one */
+    *prop->bootindex = boot_index;
+
+    add_boot_device_path(*prop->bootindex, prop->dev, prop->suffix);
+
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
+}
+
+static void property_release_bootindex(Object *obj, const char *name,
+                                       void *opaque)
+
+{
+    BootIndexProperty *prop = opaque;
+
+    del_boot_device_path(prop->dev, prop->suffix);
+    g_free(prop);
+}
+
+void device_add_bootindex_property(Object *obj, int32_t *bootindex,
+                                   const char *name, const char *suffix,
+                                   DeviceState *dev, Error **errp)
+{
+    Error *local_err = NULL;
+    BootIndexProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->bootindex = bootindex;
+    prop->suffix = suffix;
+    prop->dev = dev;
+
+    object_property_add(obj, name, "int32",
+                        device_get_bootindex,
+                        device_set_bootindex,
+                        property_release_bootindex,
+                        prop, &local_err);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        g_free(prop);
+        return;
+    }
+    /* initialize devices' bootindex property to -1 */
+    object_property_set_int(obj, -1, name, NULL);
+}
index 6c86a6b59e8c6dc7dbb75e240f2829985b1851b2..34c1d8f1c92589e5f3d814673cd3a4424aa36f94 100644 (file)
@@ -2216,9 +2216,6 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
         error_propagate(errp, err);
         return;
     }
-
-    add_boot_device_path(isa->bootindexA, dev, "/floppy@0");
-    add_boot_device_path(isa->bootindexB, dev, "/floppy@1");
 }
 
 static void sysbus_fdc_initfn(Object *obj)
@@ -2291,8 +2288,6 @@ static Property isa_fdc_properties[] = {
     DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
     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_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
                     0, true),
     DEFINE_PROP_END_OF_LIST(),
@@ -2310,11 +2305,24 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
+static void isabus_fdc_instance_init(Object *obj)
+{
+    FDCtrlISABus *isa = ISA_FDC(obj);
+
+    device_add_bootindex_property(obj, &isa->bootindexA,
+                                  "bootindexA", "/floppy@0",
+                                  DEVICE(obj), NULL);
+    device_add_bootindex_property(obj, &isa->bootindexB,
+                                  "bootindexB", "/floppy@1",
+                                  DEVICE(obj), NULL);
+}
+
 static const TypeInfo isa_fdc_info = {
     .name          = TYPE_ISA_FDC,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(FDCtrlISABus),
     .class_init    = isabus_fdc_class_init,
+    .instance_init = isabus_fdc_instance_init,
 };
 
 static const VMStateDescription vmstate_sysbus_fdc ={
index b010c9b00f7f27f63d4c5d59719674c4f2ab6cdf..9a95f7530b7328086a05dab31fbc5a47756530a6 100644 (file)
@@ -24,6 +24,8 @@
 #include <hw/hw.h>
 #include <hw/pci/msix.h>
 #include <hw/pci/pci.h>
+#include "sysemu/sysemu.h"
+#include "qapi/visitor.h"
 
 #include "nvme.h"
 
@@ -871,11 +873,53 @@ static void nvme_class_init(ObjectClass *oc, void *data)
     dc->vmsd = &nvme_vmstate;
 }
 
+static void nvme_get_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    NvmeCtrl *s = NVME(obj);
+
+    visit_type_int32(v, &s->conf.bootindex, name, errp);
+}
+
+static void nvme_set_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    NvmeCtrl *s = NVME(obj);
+    int32_t boot_index;
+    Error *local_err = NULL;
+
+    visit_type_int32(v, &boot_index, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* check whether bootindex is present in fw_boot_order list  */
+    check_boot_index(boot_index, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* change bootindex to a new one */
+    s->conf.bootindex = boot_index;
+
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
+}
+
+static void nvme_instance_init(Object *obj)
+{
+    object_property_add(obj, "bootindex", "int32",
+                        nvme_get_bootindex,
+                        nvme_set_bootindex, NULL, NULL, NULL);
+    object_property_set_int(obj, -1, "bootindex", NULL);
+}
+
 static const TypeInfo nvme_info = {
     .name          = "nvme",
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(NvmeCtrl),
     .class_init    = nvme_class_init,
+    .instance_init = nvme_instance_init,
 };
 
 static void nvme_register_types(void)
index 45e0c8f6e9731de20caed6d0603071451187d7bc..1fa97709c8c1b99d6a1d63965c026f3a58c40d73 100644 (file)
@@ -768,8 +768,6 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     bdrv_set_guest_block_size(s->bs, s->conf->logical_block_size);
 
     bdrv_iostatus_enable(s->bs);
-
-    add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
 }
 
 static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
@@ -794,6 +792,9 @@ static void virtio_blk_instance_init(Object *obj)
                              (Object **)&s->blk.iothread,
                              qdev_prop_allow_set_link_before_realize,
                              OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
+    device_add_bootindex_property(obj, &s->blk.conf.bootindex,
+                                  "bootindex", "/disk@0,0",
+                                  DEVICE(obj), NULL);
 }
 
 static Property virtio_blk_properties[] = {
index 13b9de08f1637a2cc4fee1571a0b812a54b4b7f9..bb206da05fa34622578cf7394faeba6acec37046 100644 (file)
@@ -1825,8 +1825,6 @@ static int assigned_initfn(struct PCIDevice *pci_dev)
 
     assigned_dev_load_option_rom(dev);
 
-    add_boot_device_path(dev->bootindex, &pci_dev->qdev, NULL);
-
     return 0;
 
 assigned_out:
@@ -1850,13 +1848,22 @@ static void assigned_exitfn(struct PCIDevice *pci_dev)
     free_assigned_device(dev);
 }
 
+static void assigned_dev_instance_init(Object *obj)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(obj);
+    AssignedDevice *d = DO_UPCAST(AssignedDevice, dev, PCI_DEVICE(obj));
+
+    device_add_bootindex_property(obj, &d->bootindex,
+                                  "bootindex", NULL,
+                                  &pci_dev->qdev, NULL);
+}
+
 static Property assigned_dev_properties[] = {
     DEFINE_PROP_PCI_HOST_DEVADDR("host", AssignedDevice, host),
     DEFINE_PROP_BIT("prefer_msi", AssignedDevice, features,
                     ASSIGNED_DEVICE_PREFER_MSI_BIT, false),
     DEFINE_PROP_BIT("share_intx", AssignedDevice, features,
                     ASSIGNED_DEVICE_SHARE_INTX_BIT, true),
-    DEFINE_PROP_INT32("bootindex", AssignedDevice, bootindex, -1),
     DEFINE_PROP_STRING("configfd", AssignedDevice, configfd_name),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -1882,6 +1889,7 @@ static const TypeInfo assign_info = {
     .parent             = TYPE_PCI_DEVICE,
     .instance_size      = sizeof(AssignedDevice),
     .class_init         = assign_class_init,
+    .instance_init      = assigned_dev_instance_init,
 };
 
 static void assign_register_types(void)
index efab95b3208fcc3a62a20bfc0fc6d0d48f78e046..9814ef0d247dddacdcb1426c13fc4f0174836fb1 100644 (file)
@@ -23,6 +23,7 @@
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "sysemu/sysemu.h"
+#include "qapi/visitor.h"
 
 /* --------------------------------- */
 
@@ -191,6 +192,51 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     return 0;
 }
 
+static void ide_dev_get_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    IDEDevice *d = IDE_DEVICE(obj);
+
+    visit_type_int32(v, &d->conf.bootindex, name, errp);
+}
+
+static void ide_dev_set_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    IDEDevice *d = IDE_DEVICE(obj);
+    int32_t boot_index;
+    Error *local_err = NULL;
+
+    visit_type_int32(v, &boot_index, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* check whether bootindex is present in fw_boot_order list  */
+    check_boot_index(boot_index, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* change bootindex to a new one */
+    d->conf.bootindex = boot_index;
+
+    if (d->unit != -1) {
+        add_boot_device_path(d->conf.bootindex, &d->qdev,
+                             d->unit ? "/disk@1" : "/disk@0");
+    }
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
+}
+
+static void ide_dev_instance_init(Object *obj)
+{
+    object_property_add(obj, "bootindex", "int32",
+                        ide_dev_get_bootindex,
+                        ide_dev_set_bootindex, NULL, NULL, NULL);
+    object_property_set_int(obj, -1, "bootindex", NULL);
+}
+
 static int ide_hd_initfn(IDEDevice *dev)
 {
     return ide_dev_initfn(dev, IDE_HD);
@@ -300,6 +346,7 @@ static const TypeInfo ide_device_type_info = {
     .abstract = true,
     .class_size = sizeof(IDEDeviceClass),
     .class_init = ide_device_class_init,
+    .instance_init = ide_dev_instance_init,
 };
 
 static void ide_register_types(void)
index d66f3d2425b85fd54efd9f2e73025a724fef207f..b5e798173b7eb0b4dd2bcf69189f84eaa505da4f 100644 (file)
@@ -4296,7 +4296,6 @@ static int vfio_initfn(PCIDevice *pdev)
         }
     }
 
-    add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL);
     vfio_register_err_notifier(vdev);
 
     return 0;
@@ -4365,13 +4364,22 @@ post_reset:
     vfio_pci_post_reset(vdev);
 }
 
+static void vfio_instance_init(Object *obj)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(obj);
+    VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, PCI_DEVICE(obj));
+
+    device_add_bootindex_property(obj, &vdev->bootindex,
+                                  "bootindex", NULL,
+                                  &pci_dev->qdev, NULL);
+}
+
 static Property vfio_pci_dev_properties[] = {
     DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
     DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
                        intx.mmap_timeout, 1100),
     DEFINE_PROP_BIT("x-vga", VFIODevice, features,
                     VFIO_FEATURE_ENABLE_VGA_BIT, false),
-    DEFINE_PROP_INT32("bootindex", VFIODevice, bootindex, -1),
     /*
      * TODO - support passed fds... is this necessary?
      * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
@@ -4407,6 +4415,7 @@ static const TypeInfo vfio_pci_dev_info = {
     .parent = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VFIODevice),
     .class_init = vfio_pci_dev_class_init,
+    .instance_init = vfio_instance_init,
 };
 
 static void register_vfio_pci_dev_type(void)
index 272df00f4ab9547addd6e7a4e9bacfbe0d020e82..e33a4da9fa2a6b708f10301f523b312710b11ee8 100644 (file)
@@ -1569,8 +1569,6 @@ static int pci_e1000_init(PCIDevice *pci_dev)
 
     qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
 
-    add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
-
     d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
     d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
 
@@ -1621,10 +1619,19 @@ static void e1000_class_init(ObjectClass *klass, void *data)
     dc->props = e1000_properties;
 }
 
+static void e1000_instance_init(Object *obj)
+{
+    E1000State *n = E1000(obj);
+    device_add_bootindex_property(obj, &n->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(n), NULL);
+}
+
 static const TypeInfo e1000_base_info = {
     .name          = TYPE_E1000_BASE,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(E1000State),
+    .instance_init = e1000_instance_init,
     .class_size    = sizeof(E1000BaseClass),
     .abstract      = true,
 };
@@ -1668,6 +1675,7 @@ static void e1000_register_types(void)
         type_info.parent = TYPE_E1000_BASE;
         type_info.class_data = (void *)info;
         type_info.class_init = e1000_class_init;
+        type_info.instance_init = e1000_instance_init;
 
         type_register(&type_info);
     }
index 3cd826acccf66ecbe769d1101c8d157546f73ec9..4877bfd4d37f21c765fc60aa6da5f937a691da2d 100644 (file)
@@ -1901,11 +1901,17 @@ static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate->name = qemu_get_queue(s->nic)->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;
 }
 
+static void eepro100_instance_init(Object *obj)
+{
+    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, PCI_DEVICE(obj));
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(s), NULL);
+}
+
 static E100PCIDeviceInfo e100_devices[] = {
     {
         .name = "i82550",
@@ -2104,7 +2110,8 @@ static void eepro100_register_types(void)
         type_info.parent = TYPE_PCI_DEVICE;
         type_info.class_init = eepro100_class_init;
         type_info.instance_size = sizeof(EEPRO100State);
-        
+        type_info.instance_init = eepro100_instance_init;
+
         type_register(&type_info);
     }
 }
index 7811a9edc24a0e3fd94c4d1f68f36cd7ae620c6d..a1c49f1b972c8156c198c4faff970522e79bbb1a 100644 (file)
@@ -42,6 +42,7 @@
 #include "hw/sparc/sun4m.h"
 #include "pcnet.h"
 #include "trace.h"
+#include "sysemu/sysemu.h"
 
 #define TYPE_LANCE "lance"
 #define SYSBUS_PCNET(obj) \
@@ -143,6 +144,16 @@ static void lance_reset(DeviceState *dev)
     pcnet_h_reset(&d->state);
 }
 
+static void lance_instance_init(Object *obj)
+{
+    SysBusPCNetState *d = SYSBUS_PCNET(obj);
+    PCNetState *s = &d->state;
+
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(obj), NULL);
+}
+
 static Property lance_properties[] = {
     DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque),
     DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf),
@@ -169,6 +180,7 @@ static const TypeInfo lance_info = {
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(SysBusPCNetState),
     .class_init    = lance_class_init,
+    .instance_init = lance_instance_init,
 };
 
 static void lance_register_types(void)
index 6eb1dac8dce9be4ecfd94f69eae62bbfefdf840c..82e2ba17c13c23d1bbe888aa2de3fbabf46f928a 100644 (file)
@@ -28,6 +28,7 @@
 #include "net/net.h"
 #include "ne2000.h"
 #include "exec/address-spaces.h"
+#include "qapi/visitor.h"
 
 #define TYPE_ISA_NE2000 "ne2k_isa"
 #define ISA_NE2000(obj) OBJECT_CHECK(ISANE2000State, (obj), TYPE_ISA_NE2000)
@@ -101,11 +102,54 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 }
 
+static void isa_ne2000_get_bootindex(Object *obj, Visitor *v, void *opaque,
+                                     const char *name, Error **errp)
+{
+    ISANE2000State *isa = ISA_NE2000(obj);
+    NE2000State *s = &isa->ne2000;
+
+    visit_type_int32(v, &s->c.bootindex, name, errp);
+}
+
+static void isa_ne2000_set_bootindex(Object *obj, Visitor *v, void *opaque,
+                                     const char *name, Error **errp)
+{
+    ISANE2000State *isa = ISA_NE2000(obj);
+    NE2000State *s = &isa->ne2000;
+    int32_t boot_index;
+    Error *local_err = NULL;
+
+    visit_type_int32(v, &boot_index, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* check whether bootindex is present in fw_boot_order list  */
+    check_boot_index(boot_index, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* change bootindex to a new one */
+    s->c.bootindex = boot_index;
+
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
+}
+
+static void isa_ne2000_instance_init(Object *obj)
+{
+    object_property_add(obj, "bootindex", "int32",
+                        isa_ne2000_get_bootindex,
+                        isa_ne2000_set_bootindex, NULL, NULL, NULL);
+    object_property_set_int(obj, -1, "bootindex", NULL);
+}
 static const TypeInfo ne2000_isa_info = {
     .name          = TYPE_ISA_NE2000,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(ISANE2000State),
     .class_init    = isa_ne2000_class_initfn,
+    .instance_init = isa_ne2000_instance_init,
 };
 
 static void ne2000_isa_register_types(void)
index a62d12d92de6c125d6f2de148a097b2b5f8efdef..3ab2d036961cdd5e150e2c0888c371e1d53a961a 100644 (file)
@@ -738,8 +738,6 @@ static int pci_ne2000_init(PCIDevice *pci_dev)
                           object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
 
-    add_boot_device_path(s->c.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
-
     return 0;
 }
 
@@ -752,6 +750,17 @@ static void pci_ne2000_exit(PCIDevice *pci_dev)
     qemu_free_irq(s->irq);
 }
 
+static void ne2000_instance_init(Object *obj)
+{
+    PCIDevice *pci_dev = PCI_DEVICE(obj);
+    PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
+    NE2000State *s = &d->ne2000;
+
+    device_add_bootindex_property(obj, &s->c.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  &pci_dev->qdev, NULL);
+}
+
 static Property ne2000_properties[] = {
     DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
     DEFINE_PROP_END_OF_LIST(),
@@ -778,6 +787,7 @@ static const TypeInfo ne2000_info = {
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCINE2000State),
     .class_init    = ne2000_class_init,
+    .instance_init = ne2000_instance_init,
 };
 
 static void ne2000_register_types(void)
index 50ffe914e0924823b892345ec7490369419b5b6e..fb5f5d62379d95de56e84cd450ab28f7b46f2236 100644 (file)
@@ -32,6 +32,7 @@
 #include "hw/loader.h"
 #include "qemu/timer.h"
 #include "sysemu/dma.h"
+#include "sysemu/sysemu.h"
 
 #include "pcnet.h"
 
@@ -344,6 +345,16 @@ static void pci_reset(DeviceState *dev)
     pcnet_h_reset(&d->state);
 }
 
+static void pcnet_instance_init(Object *obj)
+{
+    PCIPCNetState *d = PCI_PCNET(obj);
+    PCNetState *s = &d->state;
+
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(obj), NULL);
+}
+
 static Property pcnet_properties[] = {
     DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
     DEFINE_PROP_END_OF_LIST(),
@@ -372,6 +383,7 @@ static const TypeInfo pcnet_info = {
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCIPCNetState),
     .class_init    = pcnet_class_init,
+    .instance_init = pcnet_instance_init,
 };
 
 static void pci_pcnet_register_types(void)
index 5299d52a8f6a56e06633c5252885203dcdcdf55e..d344c15da0f860e6462a852e9c6e75a443226c48 100644 (file)
@@ -1735,8 +1735,6 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
     s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 
-    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
-
     /* Initialize the PROM */
 
     /*
index 9dee6f3e2c5570666157059f91a949191bf2e23b..f8e8a6f6ba08e5ef57ad1d4a04691d5431b7d1cf 100644 (file)
@@ -66,5 +66,4 @@ void pcnet_set_link_status(NetClientState *nc);
 void pcnet_common_cleanup(PCNetState *d);
 int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
 extern const VMStateDescription vmstate_pcnet;
-
 #endif
index 6e59f3819b6bef4c838890707892ab7726b402ab..8b8a1b18af491d3b1ad21cc0a1d7deafe4f62438 100644 (file)
@@ -3538,11 +3538,18 @@ static int pci_rtl8139_init(PCIDevice *dev)
     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s);
     rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 
-    add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0");
-
     return 0;
 }
 
+static void rtl8139_instance_init(Object *obj)
+{
+    RTL8139State *s = RTL8139(obj);
+
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(obj), NULL);
+}
+
 static Property rtl8139_properties[] = {
     DEFINE_NIC_PROPERTIES(RTL8139State, conf),
     DEFINE_PROP_END_OF_LIST(),
@@ -3571,6 +3578,7 @@ static const TypeInfo rtl8139_info = {
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(RTL8139State),
     .class_init    = rtl8139_class_init,
+    .instance_init = rtl8139_instance_init,
 };
 
 static void rtl8139_register_types(void)
index 23c47d397c599af259a4470a914be206e0729bee..2c8b0382274c86e2851c4622fc4fb54a0e03039f 100644 (file)
@@ -221,11 +221,18 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev)
                             object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
     qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
 
-    add_boot_device_path(dev->nicconf.bootindex, DEVICE(dev), "");
-
     return 0;
 }
 
+static void spapr_vlan_instance_init(Object *obj)
+{
+    VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(obj);
+
+    device_add_bootindex_property(obj, &dev->nicconf.bootindex,
+                                  "bootindex", "",
+                                  DEVICE(dev), NULL);
+}
+
 void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
 {
     DeviceState *dev;
@@ -553,6 +560,7 @@ static const TypeInfo spapr_vlan_info = {
     .parent        = TYPE_VIO_SPAPR_DEVICE,
     .instance_size = sizeof(VIOsPAPRVLANDevice),
     .class_init    = spapr_vlan_class_init,
+    .instance_init = spapr_vlan_instance_init,
 };
 
 static void spapr_vlan_register_types(void)
index 2040eac9a184acad06d9defeb0fc51b264af70e0..9b88775fac31f11bb2ac4cf2c6e97bc3558967b5 100644 (file)
@@ -1661,8 +1661,6 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
     n->qdev = dev;
     register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
-
-    add_boot_device_path(n->nic_conf.bootindex, dev, "/ethernet-phy@0");
 }
 
 static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
@@ -1714,6 +1712,9 @@ static void virtio_net_instance_init(Object *obj)
      * Can be overriden with virtio_net_set_config_size.
      */
     n->config_size = sizeof(struct virtio_net_config);
+    device_add_bootindex_property(obj, &n->nic_conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(n), NULL);
 }
 
 static Property virtio_net_properties[] = {
index f246fa1c45ae564e7d88cb7f333d85cf97df2795..8eea58989b5a55416567df388502a75465719a00 100644 (file)
@@ -2172,11 +2172,16 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev)
     register_savevm(dev, "vmxnet3-msix", -1, 1,
                     vmxnet3_msix_save, vmxnet3_msix_load, s);
 
-    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
-
     return 0;
 }
 
+static void vmxnet3_instance_init(Object *obj)
+{
+    VMXNET3State *s = VMXNET3(obj);
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  DEVICE(obj), NULL);
+}
 
 static void vmxnet3_pci_uninit(PCIDevice *pci_dev)
 {
@@ -2524,6 +2529,7 @@ static const TypeInfo vmxnet3_info = {
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(VMXNET3State),
     .class_init    = vmxnet3_class_init,
+    .instance_init = vmxnet3_instance_init,
 };
 
 static void vmxnet3_register_types(void)
index b71d25156843220e3ccad77ade4e77e6f8f02c3a..e7ed27e24289eb0f47ed778ce7fc7e5f5362eeaf 100644 (file)
@@ -402,6 +402,26 @@ static void fw_cfg_add_bytes_read_callback(FWCfgState *s, uint16_t key,
     s->entries[arch][key].callback_opaque = callback_opaque;
 }
 
+static void *fw_cfg_modify_bytes_read(FWCfgState *s, uint16_t key,
+                                              void *data, size_t len)
+{
+    void *ptr;
+    int arch = !!(key & FW_CFG_ARCH_LOCAL);
+
+    key &= FW_CFG_ENTRY_MASK;
+
+    assert(key < FW_CFG_MAX_ENTRY && len < UINT32_MAX);
+
+    /* return the old data to the function caller, avoid memory leak */
+    ptr = s->entries[arch][key].data;
+    s->entries[arch][key].data = data;
+    s->entries[arch][key].len = len;
+    s->entries[arch][key].callback_opaque = NULL;
+    s->entries[arch][key].callback = NULL;
+
+    return ptr;
+}
+
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
 {
     fw_cfg_add_bytes_read_callback(s, key, NULL, NULL, data, len);
@@ -499,13 +519,42 @@ void fw_cfg_add_file(FWCfgState *s,  const char *filename,
     fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
 }
 
-static void fw_cfg_machine_ready(struct Notifier *n, void *data)
+void *fw_cfg_modify_file(FWCfgState *s, const char *filename,
+                        void *data, size_t len)
+{
+    int i, index;
+
+    assert(s->files);
+
+    index = be32_to_cpu(s->files->count);
+    assert(index < FW_CFG_FILE_SLOTS);
+
+    for (i = 0; i < index; i++) {
+        if (strcmp(filename, s->files->f[i].name) == 0) {
+            return fw_cfg_modify_bytes_read(s, FW_CFG_FILE_FIRST + i,
+                                     data, len);
+        }
+    }
+    /* add new one */
+    fw_cfg_add_file_callback(s, filename, NULL, NULL, data, len);
+    return NULL;
+}
+
+static void fw_cfg_machine_reset(void *opaque)
 {
+    void *ptr;
     size_t len;
-    FWCfgState *s = container_of(n, FWCfgState, machine_ready);
+    FWCfgState *s = opaque;
     char *bootindex = get_boot_devices_list(&len, false);
 
-    fw_cfg_add_file(s, "bootorder", (uint8_t*)bootindex, len);
+    ptr = fw_cfg_modify_file(s, "bootorder", (uint8_t *)bootindex, len);
+    g_free(ptr);
+}
+
+static void fw_cfg_machine_ready(struct Notifier *n, void *data)
+{
+    FWCfgState *s = container_of(n, FWCfgState, machine_ready);
+    qemu_register_reset(fw_cfg_machine_reset, s);
 }
 
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
index 5a9e52b777e4fc98af404671e029aef41cd027bc..29ecdb4194cc9adfaf0b14b81432d7253b3afadb 100644 (file)
@@ -162,6 +162,8 @@ static void s390_virtio_net_instance_init(Object *obj)
 
     virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
                                 TYPE_VIRTIO_NET);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
@@ -183,6 +185,8 @@ static void s390_virtio_blk_instance_init(Object *obj)
                                 TYPE_VIRTIO_BLK);
     object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
                               &error_abort);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
index 4438b6fc74c4fda194efd0f9b694293a320c5ca9..f5ec94657f9efdf5026383941ab2a4a6d65e5601 100644 (file)
@@ -795,6 +795,8 @@ static void virtio_ccw_net_instance_init(Object *obj)
 
     virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
                                 TYPE_VIRTIO_NET);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
@@ -817,6 +819,8 @@ static void virtio_ccw_blk_instance_init(Object *obj)
                                 TYPE_VIRTIO_BLK);
     object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
                               &error_abort);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
index d33030e6e9ca689e840643520edb13e612fe62ef..022a524074457076777a95185079523cd7f41581 100644 (file)
@@ -233,7 +233,8 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     dev = qdev_create(&bus->qbus, driver);
     qdev_prop_set_uint32(dev, "scsi-id", unit);
     if (bootindex >= 0) {
-        qdev_prop_set_int32(dev, "bootindex", bootindex);
+        object_property_set_int(OBJECT(dev), bootindex, "bootindex",
+                                &error_abort);
     }
     if (object_property_find(OBJECT(dev), "removable", NULL)) {
         qdev_prop_set_bit(dev, "removable", removable);
@@ -2006,6 +2007,16 @@ static void scsi_device_class_init(ObjectClass *klass, void *data)
     k->props     = scsi_props;
 }
 
+static void scsi_dev_instance_init(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    SCSIDevice *s = DO_UPCAST(SCSIDevice, qdev, dev);
+
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", NULL,
+                                  &s->qdev, NULL);
+}
+
 static const TypeInfo scsi_device_type_info = {
     .name = TYPE_SCSI_DEVICE,
     .parent = TYPE_DEVICE,
@@ -2013,6 +2024,7 @@ static const TypeInfo scsi_device_type_info = {
     .abstract = true,
     .class_size = sizeof(SCSIDeviceClass),
     .class_init = scsi_device_class_init,
+    .instance_init = scsi_dev_instance_init,
 };
 
 static void scsi_register_types(void)
index 7a7938a5bffed130fa2d8b4e1f2118d919723845..ae9e08dd13912448a81a55c336e06be26c9b07a0 100644 (file)
@@ -2269,7 +2269,6 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
     bdrv_set_guest_block_size(s->qdev.conf.bs, s->qdev.blocksize);
 
     bdrv_iostatus_enable(s->qdev.conf.bs);
-    add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
 }
 
 static void scsi_hd_realize(SCSIDevice *dev, Error **errp)
@@ -2662,7 +2661,6 @@ static const TypeInfo scsi_cd_info = {
 #ifdef __linux__
 static Property scsi_block_properties[] = {
     DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
-    DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
index 01bca084e6e3b161e0a62d73de5916dc64282ac2..84a1d5bfe30ebbb58ea54ff5d68d5f32e3f10e3c 100644 (file)
@@ -413,9 +413,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
     /* define device state */
     s->type = scsiid.scsi_type;
     DPRINTF("device type %d\n", s->type);
-    if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
-        add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
-    }
 
     switch (s->type) {
     case TYPE_TAPE:
@@ -463,7 +460,6 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 
 static Property scsi_generic_properties[] = {
     DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
-    DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
index 23e3c45b5f84527015078d4756184e6e14c71c42..5b95d5c382a1be0c0bb22d7ae65175aa6c9a3a2d 100644 (file)
@@ -1371,8 +1371,16 @@ static void usb_net_realize(USBDevice *dev, Error **errrp)
              s->conf.macaddr.a[4],
              s->conf.macaddr.a[5]);
     usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
+}
+
+static void usb_net_instance_init(Object *obj)
+{
+    USBDevice *dev = USB_DEVICE(obj);
+    USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
 
-    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
+    device_add_bootindex_property(obj, &s->conf.bootindex,
+                                  "bootindex", "/ethernet-phy@0",
+                                  &dev->qdev, NULL);
 }
 
 static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
@@ -1438,6 +1446,7 @@ static const TypeInfo net_info = {
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBNetState),
     .class_init    = usb_net_class_initfn,
+    .instance_init = usb_net_instance_init,
 };
 
 static void usb_net_register_types(void)
index b005783fdfcec58bb14c25ac56f0ca326fa55dc2..5bfc72ca45d72c849ddedd54233ef87e8a7a37c8 100644 (file)
@@ -17,6 +17,7 @@
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/blockdev.h"
+#include "qapi/visitor.h"
 
 //#define DEBUG_MSD
 
@@ -59,6 +60,7 @@ typedef struct {
     /* usb-storage only */
     BlockConf conf;
     uint32_t removable;
+    SCSIDevice *scsi_dev;
 } MSDState;
 
 struct usb_msd_cbw {
@@ -633,6 +635,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
         return;
     }
     usb_msd_handle_reset(dev);
+    s->scsi_dev = scsi_dev;
 
     if (bdrv_key_required(bs)) {
         if (cur_mon) {
@@ -765,6 +768,54 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
     usb_msd_class_initfn_common(klass);
 }
 
+static void usb_msd_get_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    USBDevice *dev = USB_DEVICE(obj);
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+    visit_type_int32(v, &s->conf.bootindex, name, errp);
+}
+
+static void usb_msd_set_bootindex(Object *obj, Visitor *v, void *opaque,
+                                  const char *name, Error **errp)
+{
+    USBDevice *dev = USB_DEVICE(obj);
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+    int32_t boot_index;
+    Error *local_err = NULL;
+
+    visit_type_int32(v, &boot_index, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* check whether bootindex is present in fw_boot_order list  */
+    check_boot_index(boot_index, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    /* change bootindex to a new one */
+    s->conf.bootindex = boot_index;
+
+    if (s->scsi_dev) {
+        object_property_set_int(OBJECT(s->scsi_dev), boot_index, "bootindex",
+                                &error_abort);
+    }
+
+out:
+    if (local_err) {
+        error_propagate(errp, local_err);
+    }
+}
+
+static void usb_msd_instance_init(Object *obj)
+{
+    object_property_add(obj, "bootindex", "int32",
+                        usb_msd_get_bootindex,
+                        usb_msd_set_bootindex, NULL, NULL, NULL);
+    object_property_set_int(obj, -1, "bootindex", NULL);
+}
+
 static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
 {
     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
@@ -780,6 +831,7 @@ static const TypeInfo msd_info = {
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(MSDState),
     .class_init    = usb_msd_class_initfn_storage,
+    .instance_init = usb_msd_instance_init,
 };
 
 static const TypeInfo bot_info = {
index 45b74e53074d9479afb6a76141a1fa65fd5f8eac..d2d161bc6e2acb9dadcfe8f3495f57dda402341e 100644 (file)
@@ -978,10 +978,19 @@ static void usb_host_realize(USBDevice *udev, Error **errp)
     qemu_add_exit_notifier(&s->exit);
 
     QTAILQ_INSERT_TAIL(&hostdevs, s, next);
-    add_boot_device_path(s->bootindex, &udev->qdev, NULL);
     usb_host_auto_check(NULL);
 }
 
+static void usb_host_instance_init(Object *obj)
+{
+    USBDevice *udev = USB_DEVICE(obj);
+    USBHostDevice *s = USB_HOST_DEVICE(udev);
+
+    device_add_bootindex_property(obj, &s->bootindex,
+                                  "bootindex", NULL,
+                                  &udev->qdev, NULL);
+}
+
 static void usb_host_handle_destroy(USBDevice *udev)
 {
     USBHostDevice *s = USB_HOST_DEVICE(udev);
@@ -1465,7 +1474,6 @@ static Property usb_host_dev_properties[] = {
     DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0),
     DEFINE_PROP_UINT32("isobufs",  USBHostDevice, iso_urb_count,    4),
     DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames,   32),
-    DEFINE_PROP_INT32("bootindex", USBHostDevice, bootindex,        -1),
     DEFINE_PROP_UINT32("loglevel",  USBHostDevice, loglevel,
                        LIBUSB_LOG_LEVEL_WARNING),
     DEFINE_PROP_BIT("pipeline",    USBHostDevice, options,
@@ -1498,6 +1506,7 @@ static TypeInfo usb_host_dev_info = {
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBHostDevice),
     .class_init    = usb_host_class_initfn,
+    .instance_init = usb_host_instance_init,
 };
 
 static void usb_host_register_types(void)
index e2c98962a24d29b3dd21d57f66f697a061f98c0b..9fbd59e5ee038172abf61067e4b6504a6d9a6cdb 100644 (file)
@@ -1401,7 +1401,6 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
                           usbredir_chardev_read, usbredir_chardev_event, dev);
 
     qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
-    add_boot_device_path(dev->bootindex, &udev->qdev, NULL);
 }
 
 static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
@@ -2471,7 +2470,6 @@ static Property usbredir_properties[] = {
     DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
     DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
     DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
-    DEFINE_PROP_INT32("bootindex", USBRedirDevice, bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2496,11 +2494,22 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
+static void usbredir_instance_init(Object *obj)
+{
+    USBDevice *udev = USB_DEVICE(obj);
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+
+    device_add_bootindex_property(obj, &dev->bootindex,
+                                  "bootindex", NULL,
+                                  &udev->qdev, NULL);
+}
+
 static const TypeInfo usbredir_dev_info = {
     .name          = "usb-redir",
     .parent        = TYPE_USB_DEVICE,
     .instance_size = sizeof(USBRedirDevice),
     .class_init    = usbredir_class_initfn,
+    .instance_init = usbredir_instance_init,
 };
 
 static void usbredir_register_types(void)
index 10abd657aafbaf633fa39ff19da0ea528f4b5b3c..ae7fef96d581a170d29f008ad229c3562f3a1229 100644 (file)
@@ -1115,6 +1115,8 @@ static void virtio_blk_pci_instance_init(Object *obj)
                                 TYPE_VIRTIO_BLK);
     object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
                               &error_abort);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static const TypeInfo virtio_blk_pci_info = {
@@ -1466,6 +1468,8 @@ static void virtio_net_pci_instance_init(Object *obj)
 
     virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
                                 TYPE_VIRTIO_NET);
+    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
+                              "bootindex", &error_abort);
 }
 
 static const TypeInfo virtio_net_pci_info = {
index 3a0148848b713a95d02ff7b5d9208b087f21452f..867a22664332280bbe5624df4886b80cc4c5bfbe 100644 (file)
@@ -49,7 +49,6 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
                           _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_INT32("bootindex", _state, _conf.bootindex, -1),        \
     DEFINE_PROP_UINT32("discard_granularity", _state, \
                        _conf.discard_granularity, -1)
 
index 72b1549dc4ad85dc5678710af57ef5557b011867..56e1ed71226d0194bf81f1a26b020ec609d580ac 100644 (file)
@@ -76,6 +76,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
 void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
                               FWCfgReadCallback callback, void *callback_opaque,
                               void *data, size_t len);
+void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
+                         size_t len);
 FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
                         hwaddr crl_addr, hwaddr data_addr);
 
index ed594f9bdb43497b41f16dbb6644829354c62cf0..008d610046578c5d8c5e3a21c581e54d29b1f9eb 100644 (file)
@@ -36,8 +36,7 @@ typedef struct NICConf {
 #define DEFINE_NIC_PROPERTIES(_state, _conf)                            \
     DEFINE_PROP_MACADDR("mac",   _state, _conf.macaddr),                \
     DEFINE_PROP_VLAN("vlan",     _state, _conf.peers),                   \
-    DEFINE_PROP_NETDEV("netdev", _state, _conf.peers),                   \
-    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)
+    DEFINE_PROP_NETDEV("netdev", _state, _conf.peers)
 
 
 /* Net clients */
index d8539fd602e1844c7012da6243a7ea5e580be9e0..0037a695c137ceae3a2d083add9a681f14f57c9f 100644 (file)
@@ -130,6 +130,7 @@ extern int no_shutdown;
 extern int semihosting_enabled;
 extern int old_param;
 extern int boot_menu;
+extern bool boot_strict;
 extern uint8_t *boot_splash_filedata;
 extern size_t boot_splash_filedata_size;
 extern uint8_t qemu_extra_params_fw[2];
@@ -212,6 +213,11 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
 char *get_boot_devices_list(size_t *size, bool ignore_suffixes);
 
 DeviceState *get_boot_device(uint32_t position);
+void check_boot_index(int32_t bootindex, Error **errp);
+void del_boot_device_path(DeviceState *dev, const char *suffix);
+void device_add_bootindex_property(Object *obj, int32_t *bootindex,
+                                   const char *name, const char *suffix,
+                                   DeviceState *dev, Error **errp);
 
 QemuOpts *qemu_get_machine_opts(void);
 
diff --git a/vl.c b/vl.c
index 964d63403cec347676e09a867d69c321c7665c0e..aee73e192f58d14192bef68eafe1feae23fd3a16 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -180,23 +180,12 @@ int ctrl_grab = 0;
 unsigned int nb_prom_envs = 0;
 const char *prom_envs[MAX_PROM_ENVS];
 int boot_menu;
-static bool boot_strict;
+bool boot_strict;
 uint8_t *boot_splash_filedata;
 size_t boot_splash_filedata_size;
 uint8_t qemu_extra_params_fw[2];
 
 int icount_align_option;
-typedef struct FWBootEntry FWBootEntry;
-
-struct FWBootEntry {
-    QTAILQ_ENTRY(FWBootEntry) link;
-    int32_t bootindex;
-    DeviceState *dev;
-    char *suffix;
-};
-
-static QTAILQ_HEAD(, FWBootEntry) fw_boot_order =
-    QTAILQ_HEAD_INITIALIZER(fw_boot_order);
 
 int nb_numa_nodes;
 int max_numa_nodeid;
@@ -1246,111 +1235,6 @@ static void restore_boot_order(void *opaque)
     g_free(normal_boot_order);
 }
 
-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 = g_malloc0(sizeof(FWBootEntry));
-    node->bootindex = bootindex;
-    node->suffix = g_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);
-}
-
-DeviceState *get_boot_device(uint32_t position)
-{
-    uint32_t counter = 0;
-    FWBootEntry *i = NULL;
-    DeviceState *res = NULL;
-
-    if (!QTAILQ_EMPTY(&fw_boot_order)) {
-        QTAILQ_FOREACH(i, &fw_boot_order, link) {
-            if (counter == position) {
-                res = i->dev;
-                break;
-            }
-            counter++;
-        }
-    }
-    return res;
-}
-
-/*
- * This function returns null terminated string that consist of new line
- * separated device paths.
- *
- * memory pointed by "size" is assigned total length of the array in bytes
- *
- */
-char *get_boot_devices_list(size_t *size, bool ignore_suffixes)
-{
-    FWBootEntry *i;
-    size_t total = 0;
-    char *list = NULL;
-
-    QTAILQ_FOREACH(i, &fw_boot_order, link) {
-        char *devpath = NULL, *bootpath;
-        size_t len;
-
-        if (i->dev) {
-            devpath = qdev_get_fw_dev_path(i->dev);
-            assert(devpath);
-        }
-
-        if (i->suffix && !ignore_suffixes && devpath) {
-            size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
-
-            bootpath = g_malloc(bootpathlen);
-            snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
-            g_free(devpath);
-        } else if (devpath) {
-            bootpath = devpath;
-        } else if (!ignore_suffixes) {
-            assert(i->suffix);
-            bootpath = g_strdup(i->suffix);
-        } else {
-            bootpath = g_strdup("");
-        }
-
-        if (total) {
-            list[total-1] = '\n';
-        }
-        len = strlen(bootpath) + 1;
-        list = g_realloc(list, total + len);
-        memcpy(&list[total], bootpath, len);
-        total += len;
-        g_free(bootpath);
-    }
-
-    *size = total;
-
-    if (boot_strict && *size > 0) {
-        list[total-1] = '\n';
-        list = g_realloc(list, total + 5);
-        memcpy(&list[total], "HALT", 5);
-        *size = total + 5;
-    }
-    return list;
-}
-
 static QemuOptsList qemu_smp_opts = {
     .name = "smp-opts",
     .implied_opt_name = "cpus",