Patchwork [PATCHv3,11/14] Add bootindex parameter to net/block/fd device

login
register
mail settings
Submitter Gleb Natapov
Date Nov. 10, 2010, 5:14 p.m.
Message ID <1289409261-5418-12-git-send-email-gleb@redhat.com>
Download mbox | patch
Permalink /patch/70657/
State New
Headers show

Comments

Gleb Natapov - Nov. 10, 2010, 5:14 p.m.
If bootindex is specified on command line a string that describes device
in firmware readable way is added into sorted list. Later this list will
be passed into firmware to control boot order.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
 block_int.h     |    4 +++-
 hw/e1000.c      |    7 +++++++
 hw/eepro100.c   |    6 ++++++
 hw/fdc.c        |   13 +++++++++++++
 hw/ide/qdev.c   |    7 +++++++
 hw/ne2000.c     |    6 ++++++
 hw/pcnet.c      |    6 ++++++
 hw/qdev.c       |   32 ++++++++++++++++++++++++++++++++
 hw/qdev.h       |    1 +
 hw/rtl8139.c    |    7 +++++++
 hw/usb-net.c    |    4 ++++
 hw/virtio-blk.c |    4 ++++
 hw/virtio-net.c |    4 ++++
 net.h           |    4 +++-
 sysemu.h        |    2 ++
 vl.c            |   35 +++++++++++++++++++++++++++++++++++
 16 files changed, 140 insertions(+), 2 deletions(-)
Blue Swirl - Nov. 10, 2010, 6:32 p.m.
On Wed, Nov 10, 2010 at 5:14 PM, Gleb Natapov <gleb@redhat.com> wrote:
> If bootindex is specified on command line a string that describes device
> in firmware readable way is added into sorted list. Later this list will
> be passed into firmware to control boot order.
>
> Signed-off-by: Gleb Natapov <gleb@redhat.com>
> ---
>  block_int.h     |    4 +++-
>  hw/e1000.c      |    7 +++++++
>  hw/eepro100.c   |    6 ++++++
>  hw/fdc.c        |   13 +++++++++++++
>  hw/ide/qdev.c   |    7 +++++++
>  hw/ne2000.c     |    6 ++++++
>  hw/pcnet.c      |    6 ++++++
>  hw/qdev.c       |   32 ++++++++++++++++++++++++++++++++
>  hw/qdev.h       |    1 +
>  hw/rtl8139.c    |    7 +++++++
>  hw/usb-net.c    |    4 ++++
>  hw/virtio-blk.c |    4 ++++
>  hw/virtio-net.c |    4 ++++
>  net.h           |    4 +++-
>  sysemu.h        |    2 ++
>  vl.c            |   35 +++++++++++++++++++++++++++++++++++
>  16 files changed, 140 insertions(+), 2 deletions(-)
>
> diff --git a/block_int.h b/block_int.h
> index 87e60b8..f9042a8 100644
> --- a/block_int.h
> +++ b/block_int.h
> @@ -227,6 +227,7 @@ typedef struct BlockConf {
>     uint16_t logical_block_size;
>     uint16_t min_io_size;
>     uint32_t opt_io_size;
> +    int32_t bootindex;
>  } BlockConf;
>
>  static inline unsigned int get_physical_block_exp(BlockConf *conf)
> @@ -249,6 +250,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
>     DEFINE_PROP_UINT16("physical_block_size", _state,                   \
>                        _conf.physical_block_size, 512),                 \
>     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
> -    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
> +    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
> +    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)         \
>
>  #endif /* BLOCK_INT_H */
> diff --git a/hw/e1000.c b/hw/e1000.c
> index 532efdc..009e24b 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -30,6 +30,7 @@
>  #include "net.h"
>  #include "net/checksum.h"
>  #include "loader.h"
> +#include "sysemu.h"
>
>  #include "e1000_hw.h"
>
> @@ -1148,6 +1149,12 @@ static int pci_e1000_init(PCIDevice *pci_dev)
>                           d->dev.qdev.info->name, d->dev.qdev.id, d);
>
>     qemu_format_nic_info_str(&d->nic->nc, macaddr);
> +
> +    if (d->conf.bootindex >= 0) {

Maybe these checks should be moved into add_boot_device_path, that
would simplify the callers.
Gleb Natapov - Nov. 10, 2010, 6:48 p.m.
On Wed, Nov 10, 2010 at 06:32:54PM +0000, Blue Swirl wrote:
> On Wed, Nov 10, 2010 at 5:14 PM, Gleb Natapov <gleb@redhat.com> wrote:
> > If bootindex is specified on command line a string that describes device
> > in firmware readable way is added into sorted list. Later this list will
> > be passed into firmware to control boot order.
> >
> > Signed-off-by: Gleb Natapov <gleb@redhat.com>
> > ---
> >  block_int.h     |    4 +++-
> >  hw/e1000.c      |    7 +++++++
> >  hw/eepro100.c   |    6 ++++++
> >  hw/fdc.c        |   13 +++++++++++++
> >  hw/ide/qdev.c   |    7 +++++++
> >  hw/ne2000.c     |    6 ++++++
> >  hw/pcnet.c      |    6 ++++++
> >  hw/qdev.c       |   32 ++++++++++++++++++++++++++++++++
> >  hw/qdev.h       |    1 +
> >  hw/rtl8139.c    |    7 +++++++
> >  hw/usb-net.c    |    4 ++++
> >  hw/virtio-blk.c |    4 ++++
> >  hw/virtio-net.c |    4 ++++
> >  net.h           |    4 +++-
> >  sysemu.h        |    2 ++
> >  vl.c            |   35 +++++++++++++++++++++++++++++++++++
> >  16 files changed, 140 insertions(+), 2 deletions(-)
> >
> > diff --git a/block_int.h b/block_int.h
> > index 87e60b8..f9042a8 100644
> > --- a/block_int.h
> > +++ b/block_int.h
> > @@ -227,6 +227,7 @@ typedef struct BlockConf {
> >     uint16_t logical_block_size;
> >     uint16_t min_io_size;
> >     uint32_t opt_io_size;
> > +    int32_t bootindex;
> >  } BlockConf;
> >
> >  static inline unsigned int get_physical_block_exp(BlockConf *conf)
> > @@ -249,6 +250,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
> >     DEFINE_PROP_UINT16("physical_block_size", _state,                   \
> >                        _conf.physical_block_size, 512),                 \
> >     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
> > -    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
> > +    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
> > +    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)         \
> >
> >  #endif /* BLOCK_INT_H */
> > diff --git a/hw/e1000.c b/hw/e1000.c
> > index 532efdc..009e24b 100644
> > --- a/hw/e1000.c
> > +++ b/hw/e1000.c
> > @@ -30,6 +30,7 @@
> >  #include "net.h"
> >  #include "net/checksum.h"
> >  #include "loader.h"
> > +#include "sysemu.h"
> >
> >  #include "e1000_hw.h"
> >
> > @@ -1148,6 +1149,12 @@ static int pci_e1000_init(PCIDevice *pci_dev)
> >                           d->dev.qdev.info->name, d->dev.qdev.id, d);
> >
> >     qemu_format_nic_info_str(&d->nic->nc, macaddr);
> > +
> > +    if (d->conf.bootindex >= 0) {
> 
> Maybe these checks should be moved into add_boot_device_path, that
> would simplify the callers.
Yep, good point.

--
			Gleb.

Patch

diff --git a/block_int.h b/block_int.h
index 87e60b8..f9042a8 100644
--- a/block_int.h
+++ b/block_int.h
@@ -227,6 +227,7 @@  typedef struct BlockConf {
     uint16_t logical_block_size;
     uint16_t min_io_size;
     uint32_t opt_io_size;
+    int32_t bootindex;
 } BlockConf;
 
 static inline unsigned int get_physical_block_exp(BlockConf *conf)
@@ -249,6 +250,7 @@  static inline unsigned int get_physical_block_exp(BlockConf *conf)
     DEFINE_PROP_UINT16("physical_block_size", _state,                   \
                        _conf.physical_block_size, 512),                 \
     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
-    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0)
+    DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
+    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)         \
 
 #endif /* BLOCK_INT_H */
diff --git a/hw/e1000.c b/hw/e1000.c
index 532efdc..009e24b 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -30,6 +30,7 @@ 
 #include "net.h"
 #include "net/checksum.h"
 #include "loader.h"
+#include "sysemu.h"
 
 #include "e1000_hw.h"
 
@@ -1148,6 +1149,12 @@  static int pci_e1000_init(PCIDevice *pci_dev)
                           d->dev.qdev.info->name, d->dev.qdev.id, d);
 
     qemu_format_nic_info_str(&d->nic->nc, macaddr);
+
+    if (d->conf.bootindex >= 0) {
+        add_boot_device_path(d->conf.bootindex, &pci_dev->qdev,
+                             "ethernet-phy@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 218472d..2a7c6cb 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -46,6 +46,7 @@ 
 #include "pci.h"
 #include "net.h"
 #include "eeprom93xx.h"
+#include "sysemu.h"
 
 #define KiB 1024
 
@@ -1907,6 +1908,11 @@  static int e100_nic_init(PCIDevice *pci_dev)
     s->vmstate->name = s->nic->nc.model;
     vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
 
+    if (s->conf.bootindex >= 0) {
+        add_boot_device_path(s->conf.bootindex, &pci_dev->qdev,
+                             "ethernet-phy@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/fdc.c b/hw/fdc.c
index 5ab754b..732728e 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -35,6 +35,7 @@ 
 #include "sysbus.h"
 #include "qdev-addr.h"
 #include "blockdev.h"
+#include "sysemu.h"
 
 /********************************************************/
 /* debug Floppy devices */
@@ -523,6 +524,8 @@  typedef struct FDCtrlSysBus {
 typedef struct FDCtrlISABus {
     ISADevice busdev;
     struct FDCtrl state;
+    int32_t bootindexA;
+    int32_t bootindexB;
 } FDCtrlISABus;
 
 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
@@ -1992,6 +1995,14 @@  static int isabus_fdc_init1(ISADevice *dev)
     qdev_set_legacy_instance_id(&dev->qdev, iobase, 2);
     ret = fdctrl_init_common(fdctrl);
 
+    if (isa->bootindexA >= 0) {
+        add_boot_device_path(isa->bootindexA, &dev->qdev, "floppy@0");
+    }
+
+    if (isa->bootindexB >= 0) {
+        add_boot_device_path(isa->bootindexB, &dev->qdev, "floppy@1");
+    }
+
     return ret;
 }
 
@@ -2051,6 +2062,8 @@  static ISADeviceInfo isa_fdc_info = {
     .qdev.props = (Property[]) {
         DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
         DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
+        DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
+        DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 01a181b..dcd49aa 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -21,6 +21,7 @@ 
 #include "qemu-error.h"
 #include <hw/ide/internal.h>
 #include "blockdev.h"
+#include "sysemu.h"
 
 /* --------------------------------- */
 
@@ -143,6 +144,12 @@  static int ide_drive_initfn(IDEDevice *dev)
     if (!dev->serial) {
         dev->serial = qemu_strdup(s->drive_serial_str);
     }
+
+    if (dev->conf.bootindex >= 0) {
+        add_boot_device_path(dev->conf.bootindex, &dev->qdev,
+                             dev->unit ? "disk@1" : "disk@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 126e7cf..d0a0dc6 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -26,6 +26,7 @@ 
 #include "net.h"
 #include "ne2000.h"
 #include "loader.h"
+#include "sysemu.h"
 
 /* debug NE2000 card */
 //#define DEBUG_NE2000
@@ -746,6 +747,11 @@  static int pci_ne2000_init(PCIDevice *pci_dev)
         }
     }
 
+    if (s->c.bootindex >= 0) {
+        add_boot_device_path(s->c.bootindex, &pci_dev->qdev,
+                             "ethernet-phy@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/pcnet.c b/hw/pcnet.c
index b52935a..93595cb 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -40,6 +40,7 @@ 
 #include "loader.h"
 #include "qemu-timer.h"
 #include "qemu_socket.h"
+#include "sysemu.h"
 
 #include "pcnet.h"
 
@@ -1898,6 +1899,11 @@  int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    if (s->conf.bootindex >= 0) {
+        add_boot_device_path(s->conf.bootindex, dev, "ethernet-phy@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/qdev.c b/hw/qdev.c
index 35858cb..cc9bf43 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -820,3 +820,35 @@  int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
     return qdev_unplug(dev);
 }
+
+static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
+{
+    int l = 0;
+
+    if (dev && dev->parent_bus) {
+        char *d;
+        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
+        if (dev->parent_bus->info->get_fw_dev_path) {
+            d = dev->parent_bus->info->get_fw_dev_path(dev);
+            l += snprintf(p + l, size - l, "%s", d);
+            qemu_free(d);
+        } else {
+            l += snprintf(p + l, size - l, "%s", dev->info->name);
+        }
+    }
+    l += snprintf(p + l , size - l, "/");
+
+    return l;
+}
+
+char* qdev_get_fw_dev_path(DeviceState *dev)
+{
+    char path[128];
+    int l;
+
+    l = qdev_get_fw_dev_path_helper(dev, path, 128);
+
+    path[l-1] = '\0';
+
+    return strdup(path);
+}
diff --git a/hw/qdev.h b/hw/qdev.h
index dc669b3..13f3597 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -296,6 +296,7 @@  static inline const char *qdev_fw_name(DeviceState *dev)
     return dev->info->fw_name ? : dev->info->alias ? : dev->info->name;
 }
 
+char *qdev_get_fw_dev_path(DeviceState *dev);
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 extern struct BusInfo system_bus_info;
 
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index d92981d..56a3621 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -52,6 +52,7 @@ 
 #include "qemu-timer.h"
 #include "net.h"
 #include "loader.h"
+#include "sysemu.h"
 
 /* debug RTL8139 card */
 //#define DEBUG_RTL8139 1
@@ -3387,6 +3388,12 @@  static int pci_rtl8139_init(PCIDevice *dev)
     s->TimerExpire = 0;
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
     rtl8139_set_next_tctr_time(s, qemu_get_clock(vm_clock));
+
+    if (s->conf.bootindex >= 0) {
+        add_boot_device_path(s->conf.bootindex, &dev->qdev,
+                             "ethernet-phy@0");
+    }
+
     return 0;
 }
 
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 2287ee1..55d69f0 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -27,6 +27,7 @@ 
 #include "usb.h"
 #include "net.h"
 #include "qemu-queue.h"
+#include "sysemu.h"
 
 /*#define TRAFFIC_DEBUG*/
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -1463,6 +1464,9 @@  static int usb_net_initfn(USBDevice *dev)
              s->conf.macaddr.a[4],
              s->conf.macaddr.a[5]);
 
+    if (s->conf.bootindex >= 0)
+        add_boot_device_path(s->conf.bootindex, &dev->qdev,
+                             "ethernet@0");
     return 0;
 }
 
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index dbe2070..c8f0843 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -548,6 +548,10 @@  VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     bdrv_set_removable(s->bs, 0);
     s->bs->buffer_alignment = conf->logical_block_size;
 
+    if (conf->bootindex >= 0) {
+        add_boot_device_path(conf->bootindex, dev, "disk@0");
+    }
+
     return &s->vdev;
 }
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 7e1688c..69d48f4 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -1018,6 +1018,10 @@  VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
                     virtio_net_save, virtio_net_load, n);
     n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
 
+    if (conf->bootindex >= 0) {
+        add_boot_device_path(conf->bootindex, dev, "ethernet-phy@0");
+    }
+
     return &n->vdev;
 }
 
diff --git a/net.h b/net.h
index 44c31a9..6ceca50 100644
--- a/net.h
+++ b/net.h
@@ -17,12 +17,14 @@  typedef struct NICConf {
     MACAddr macaddr;
     VLANState *vlan;
     VLANClientState *peer;
+    int32_t bootindex;
 } NICConf;
 
 #define DEFINE_NIC_PROPERTIES(_state, _conf)                            \
     DEFINE_PROP_MACADDR("mac",   _state, _conf.macaddr),                \
     DEFINE_PROP_VLAN("vlan",     _state, _conf.vlan),                   \
-    DEFINE_PROP_NETDEV("netdev", _state, _conf.peer)
+    DEFINE_PROP_NETDEV("netdev", _state, _conf.peer),                   \
+    DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1)
 
 /* VLANs support */
 
diff --git a/sysemu.h b/sysemu.h
index 849dc8c..6b85d86 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -193,4 +193,6 @@  void rtc_change_mon_event(struct tm *tm);
 
 void register_devices(void);
 
+void add_boot_device_path(int32_t bootindex, DeviceState *dev,
+                          const char *suffix);
 #endif
diff --git a/vl.c b/vl.c
index 4bad675..8edf27a 100644
--- a/vl.c
+++ b/vl.c
@@ -232,6 +232,17 @@  const char *prom_envs[MAX_PROM_ENVS];
 const char *nvram = NULL;
 int boot_menu;
 
+typedef struct FWBootEntry FWBootEntry;
+
+struct FWBootEntry {
+    QTAILQ_ENTRY(FWBootEntry) link;
+    int32_t bootindex;
+    DeviceState *dev;
+    char *suffix;
+};
+
+QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order);
+
 int nb_numa_nodes;
 uint64_t node_mem[MAX_NODES];
 uint64_t node_cpumask[MAX_NODES];
@@ -696,6 +707,30 @@  static void restore_boot_devices(void *opaque)
     qemu_free(standard_boot_devices);
 }
 
+void add_boot_device_path(int32_t bootindex, DeviceState *dev,
+                          const char *suffix)
+{
+    FWBootEntry *node = qemu_mallocz(sizeof(FWBootEntry)), *i;
+
+    assert(dev != NULL || suffix != NULL);
+
+    node->bootindex = bootindex;
+    node->suffix = strdup(suffix);
+    node->dev = dev;
+
+    QTAILQ_FOREACH(i, &fw_boot_order, link) {
+        if (i->bootindex == bootindex) {
+            fprintf(stderr, "Two devices with same boot index %d\n", bootindex);
+            exit(1);
+        } else if (i->bootindex < bootindex) {
+            continue;
+        }
+        QTAILQ_INSERT_BEFORE(i, node, link);
+        return;
+    }
+    QTAILQ_INSERT_TAIL(&fw_boot_order, node, link);
+}
+
 static void numa_add(const char *optarg)
 {
     char option[128];