diff --git a/hw/e1000.c b/hw/e1000.c
index c326671..ea4d824 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1045,6 +1045,9 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_conf[0x3d] = 1; // interrupt pin 0
+ if (nd->secure_cookie[0])
+ pci_add_capability(&d->dev, 0x0f, 0xf0, nd->secure_cookie, 14);
+
d->mmio_index = cpu_register_io_memory(0, e1000_mmio_read,
e1000_mmio_write, d);
diff --git a/hw/eepro100.c b/hw/eepro100.c
index cb3ca09..654b389 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1754,6 +1754,9 @@ static void nic_init(PCIBus * bus, NICInfo * nd,
pci_reset(s);
+ if (nd->secure_cookie[0])
+ pci_add_capability(&d->dev, 0x0f, 0xf0, nd->secure_cookie, 14);
+
/* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
* i82559 and later support 64 or 256 word EEPROM. */
s->eeprom = eeprom93xx_new(EEPROM_SIZE);
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 3f0ccf5..c3f4e22 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -806,6 +806,10 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_register_io_region(&d->dev, 0, 0x100,
PCI_ADDRESS_SPACE_IO, ne2000_map);
+
+ if (nd->secure_cookie[0])
+ pci_add_capability(&d->dev, 0x0f, 0xf0, nd->secure_cookie, 14);
+
s = &d->ne2000;
s->irq = d->dev.irq[0];
s->pci_dev = (PCIDevice *)d;
diff --git a/hw/pci.c b/hw/pci.c
index 8252d21..05bfa4b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -536,6 +536,23 @@ static void pci_set_irq(void *opaque, int irq_num, int
level)
bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
}
+int pci_add_capability(PCIDevice *d, uint8_t cap_id, uint8_t off, uint8_t *buf,
+ int len)
+{
+ uint16_t status = le16_to_cpu(*(uint16_t*)(d->config + 0x06));
+
+ if (off + len + 2 > 0x100 || off < 0x40)
+ return -1;
+
+ d->config[0x06] = cpu_to_le16(status | 0x10);
+ d->config[off] = cap_id;
+ d->config[off + 1] = d->config[0x34];
+ d->config[0x34] = off;
+ memcpy(d->config + off + 2, buf, len);
+
+ return 0;
+}
+
/***********************************************************/
/* monitor info on PCI */
diff --git a/hw/pci.h b/hw/pci.h
index 3b1caf5..87132ca 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -117,6 +117,8 @@ typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num,
int level);
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
qemu_irq *pic, int devfn_min, int nirq);
+int pci_add_capability(PCIDevice *d, uint8_t cap_id, uint8_t off, uint8_t *buf,
+ int len);
void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 30c453c..990afb2 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2024,6 +2024,9 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_conf[0x3e] = 0x06;
pci_conf[0x3f] = 0xff;
+ if (nd->secure_cookie[0])
+ pci_add_capability(&d->dev, 0x0f, 0xf0, nd->secure_cookie, 14);
+
/* Handler for memory-mapped I/O */
d->mmio_index =
cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index c3ab854..6e4c44f 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3423,6 +3423,9 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
pci_conf[0x3d] = 1; /* interrupt pin 0 */
pci_conf[0x34] = 0xdc;
+ if (nd->secure_cookie[0])
+ pci_add_capability(&d->dev, 0x0f, 0xf0, nd->secure_cookie, 14);
+
s = &d->rtl8139;
/* I/O handler for memory-mapped I/O */
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 1f45b2d..186c6bd 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -309,6 +309,9 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int
devfn)
if (!n)
return NULL;
+ if (nd->secure_cookie[0])
+ pci_add_capability(&n->vdev.pci_dev, 0x0f, 0xf0, nd->secure_cookie,
14);
+
n->vdev.get_config = virtio_net_update_config;
n->vdev.get_features = virtio_net_get_features;
n->vdev.set_features = virtio_net_set_features;
diff --git a/net.c b/net.c
index 6af4255..000768f 100644
--- a/net.c
+++ b/net.c
@@ -1474,6 +1474,11 @@ int net_client_init(const char *device, const char *p)
if (get_param_value(buf, sizeof(buf), "model", p)) {
nd->model = strdup(buf);
}
+ if (get_param_value(buf, sizeof(buf), "trusted", p)) {
+ strncpy(nd->secure_cookie, buf, sizeof(nd->secure_cookie));
+ } else {
+ nd->secure_cookie[0] = NULL;
+ }
nd->vlan = vlan;
nb_nics++;
vlan->nb_guest_devs++;
diff --git a/net.h b/net.h
index 31c7a30..e57e6e5 100644
--- a/net.h
+++ b/net.h
@@ -50,6 +50,7 @@ struct NICInfo {
uint8_t macaddr[6];
const char *model;
VLANState *vlan;
+ uint8_t secure_cookie[14];
};
extern int nb_nics;
--
Gleb.