diff options
36 files changed, 690 insertions, 166 deletions
diff --git a/Makefile.target b/Makefile.target index 1e8d7abcb3..e9ff1eed7b 100644 --- a/Makefile.target +++ b/Makefile.target @@ -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 index 0000000000..b29970c7a3 --- /dev/null +++ b/bootdevice.c @@ -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); +} diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 6c86a6b59e..34c1d8f1c9 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -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 ={ diff --git a/hw/block/nvme.c b/hw/block/nvme.c index b010c9b00f..9a95f7530b 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -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) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 45e0c8f6e9..1fa97709c8 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -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[] = { diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 13b9de08f1..bb206da05f 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -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) diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index efab95b320..9814ef0d24 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -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) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index d66f3d2425..b5e798173b 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -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) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 272df00f4a..e33a4da9fa 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -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); } diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 3cd826accc..4877bfd4d3 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -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); } } diff --git a/hw/net/lance.c b/hw/net/lance.c index 7811a9edc2..a1c49f1b97 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -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) diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 6eb1dac8dc..82e2ba17c1 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -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) diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index a62d12d92d..3ab2d03696 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -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) diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 50ffe914e0..fb5f5d6237 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -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) diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 5299d52a8f..d344c15da0 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -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 */ /* diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h index 9dee6f3e2c..f8e8a6f6ba 100644 --- a/hw/net/pcnet.h +++ b/hw/net/pcnet.h @@ -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 diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 6e59f3819b..8b8a1b18af 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -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) diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index 23c47d397c..2c8b038227 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -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) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 2040eac9a1..9b88775fac 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -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[] = { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index f246fa1c45..8eea58989b 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -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) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index b71d251568..e7ed27e242 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -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, diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 5a9e52b777..29ecdb4194 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -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) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 4438b6fc74..f5ec94657f 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -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) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index d33030e6e9..022a524074 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -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) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 7a7938a5bf..ae9e08dd13 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -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(), }; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 01bca084e6..84a1d5bfe3 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -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(), }; diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 23e3c45b5f..5b95d5c382 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -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) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index b005783fdf..5bfc72ca45 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -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 = { diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 45b74e5307..d2d161bc6e 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -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) diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index e2c98962a2..9fbd59e5ee 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -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) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 10abd657aa..ae7fef96d5 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -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 = { diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 3a0148848b..867a226643 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -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) diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 72b1549dc4..56e1ed7122 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -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); diff --git a/include/net/net.h b/include/net/net.h index ed594f9bdb..008d610046 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -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 */ diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index d8539fd602..0037a695c1 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -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); @@ -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", |