mirror of https://gitee.com/openkylin/qemu.git
allow changing bootorder via monitor at runtime,
by making bootindex a writable qom property. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJUPjeVAAoJEEy22O7T6HE4j5QP/RtecYdC9yiOGsGcI4lrDMo8 5j61JzvY7bpPGJykXH7c8B9s3n2LQIW4rzD5mDVB/bKXPwh3SbqPBQmd1T6G7lrR 4lV+c/pvrTDE9V1k0Favbe0pbfOkaBAnMyYEYFkoK7hzVUTN6acbkz0LhXudb4ci 7V9wbSLnZZrTxB50NTJu17EIa7RCDKQR6urskrxAsJeqCAT7NQtXM5ls1dfGvHQs Tc6u4+zRqv2Rzr9YxkFKPZe55rTBMUw3fcwg9F3657dCujYvcMq8+ZwFGiMXSjll oUFxwgZn05aRQwxG1YfFDI576+f9ZCirkQBoDBwgp3ZSLTN8CLVDZ0X1FA7vjntH fr5j7D0M2ftSsUDI2E3UOzaNtbtyQaCkggl+zc0fgw7dEfbitqpUZQQ4wGngBTKJ BFkky+29MhBTLqBC38S9iUGqUbHbrqIHP/hSW8ixAGm4n8dul+ROgX4ynFZNOuxE NEA1rRspDHNVanb+gcpK0wv58vvmwbECGrovkI7ffeCo+8+MDW3ebRbQ2fIxUa4C KbPp6b5vICVcsG0+XRbjA2rNn76iJYCjc+PX1WQX6vgPYEPRah51G44KLyN/r8kj fw7wOuYomtu+2nymH/8QXBEyACiuCJLTmOykHxsrYURR3VvVeg2Z0j4e7fNOg/Is +d+cVKKkN8JLFRlXG8qu =utUi -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-bootindex-20141015-1' into staging 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>
This commit is contained in:
commit
605c690b1b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 ={
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,6 +2110,7 @@ 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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet@0");
|
||||
static void usb_net_instance_init(Object *obj)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
|
||||
|
||||
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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
118
vl.c
118
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",
|
||||
|
|
Loading…
Reference in New Issue