This patch addresses:
https://bugzilla.redhat.com/show_bug.cgi?id=781562
Along with the "rombar" option that controls whether or not a boot rom
is made visible to the guest, qemu also has a "romfile" option that
allows specifying a binary file to present as the ROM BIOS of any
emulated or passthrough PCI device. This patch adds support for
specifying romfile to both passthrough PCI devices, and emulated
network devices that attach to the guest's PCI bus (just about
everything other than ne2k_isa).
One example of the usefulness of this option is described in the
bugzilla report: 82576 sriov network adapters don't provide a ROM BIOS
for the cards virtual functions (VF), but an image of such a ROM is
available, and with this ROM visible to the guest, it can PXE boot.
In libvirt's xml, the new option is configured like this:
<hostdev>
...
<rom file='/etc/fake/boot.bin'/>
...
</hostdev
(similarly for <interface>).
---
docs/formatdomain.html.in | 22 ++++++++++++++++------
docs/schemas/domaincommon.rng | 19 +++++++++++++------
src/conf/domain_conf.c | 37 ++++++++++++++++++++++---------------
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 8 +++++---
5 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 85cdbea..afd3d22 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1737,7 +1737,7 @@
<address bus='0x06' slot='0x02'
function='0x0'/>
</source>
<boot order='1'/>
- <rom bar='off'/>
+ <rom bar='on' file='/etc/fake/boot.bin'/>
</hostdev>
</devices>
...</pre>
@@ -1779,7 +1779,7 @@
<span class="since">Since 0.8.8</span></dd>
<dt><code>rom</code></dt>
<dd>The <code>rom</code> element is used to change how a PCI
- device's ROM is presented to the guest. The <code>bar</code>
+ device's ROM is presented to the guest. The optional
<code>bar</code>
attribute can be set to "on" or "off", and determines
whether
or not the device's ROM will be visible in the guest's memory
map. (In PCI documentation, the "rombar" setting controls the
@@ -1787,7 +1787,13 @@
bar is specified, the qemu default will be used (older
versions of qemu used a default of "off", while newer qemus
have a default of "on"). <span class="since">Since
- 0.9.7</span>
+ 0.9.7 (QEMU and KVM only)</span>. The optional
+ <code>file</code> attribute is used to point to a binary file
+ to be presented to the guest as the device's ROM BIOS. This
+ can be useful, for example, to provide a PXE boot ROM for a
+ virtual function of an sr-iov capable ethernet device (which
+ has no boot ROMs for the VFs).
+ <span class="since">Since 0.9.10 (QEMU and KVM
only)</span>.
</dd>
<dt><code>address</code></dt>
<dd>The <code>address</code> element for USB devices has a
@@ -2488,7 +2494,7 @@ qemu-kvm -net nic,model=? /dev/null
<interface type='network'>
<source network='default'/>
<target dev='vnet1'/>
- <b><rom bar='off'/></b>
+ <b><rom bar='on'
file='/etc/fake/boot.bin'/></b>
</interface>
</devices>
...</pre>
@@ -2502,8 +2508,12 @@ qemu-kvm -net nic,model=? /dev/null
presence of the Base Address Register for the ROM). If no rom
bar is specified, the qemu default will be used (older
versions of qemu used a default of "off", while newer qemus
- have a default of "on"). <span class="since">Since
- 0.9.10 (QEMU and KVM only)</span>
+ have a default of "on").
+ The optional <code>file</code> attribute is used to point to a
+ binary file to be presented to the guest as the device's ROM
+ BIOS. This can be useful to provide an alternative boot ROM for a
+ network device.
+ <span class="since">Since 0.9.10 (QEMU and KVM only)</span>.
</p>
<h5><a name="elementQoS">Quality of
service</a></h5>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 6bef645..5eea745 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2812,12 +2812,19 @@
<define name="rom">
<element name="rom">
- <attribute name="bar">
- <choice>
- <value>on</value>
- <value>off</value>
- </choice>
- </attribute>
+ <optional>
+ <attribute name="bar">
+ <choice>
+ <value>on</value>
+ <value>off</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="file">
+ <ref name="absFilePath"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0799c5e..683417b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1811,6 +1811,7 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
}
memset(&info->addr, 0, sizeof(info->addr));
info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
+ VIR_FREE(info->romfile);
}
@@ -1923,16 +1924,25 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
info->master.usb.startport);
}
- if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) && info->rombar) {
- const char *rombar
- = virDomainPciRombarModeTypeToString(info->rombar);
- if (!rombar) {
- virDomainReportError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected rom bar value %d"),
- info->rombar);
- return -1;
+ if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) &&
+ (info->rombar || info->romfile)) {
+
+ virBufferAddLit(buf, " <rom");
+ if (info->rombar) {
+
+ const char *rombar = virDomainPciRombarModeTypeToString(info->rombar);
+
+ if (!rombar) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected rom bar value %d"),
+ info->rombar);
+ return -1;
+ }
+ virBufferAsprintf(buf, " bar='%s'", rombar);
}
- virBufferAsprintf(buf, " <rom bar='%s'/>\n",
rombar);
+ if (info->romfile)
+ virBufferAsprintf(buf, " file='%s'", info->romfile);
+ virBufferAddLit(buf, "/>\n");
}
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
@@ -2389,18 +2399,15 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
if (rom) {
char *rombar = virXMLPropString(rom, "bar");
- if (!rombar) {
- virDomainReportError(VIR_ERR_XML_ERROR,
- "%s", _("missing rom bar
attribute"));
- goto cleanup;
- }
- if ((info->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0) {
+ if (rombar &&
+ ((info->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0))
{
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unknown rom bar value '%s'"),
rombar);
VIR_FREE(rombar);
goto cleanup;
}
VIR_FREE(rombar);
+ info->romfile = virXMLPropString(rom, "file");
}
if (!address)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8fab383..7f33df2 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -190,6 +190,7 @@ struct _virDomainDeviceInfo {
/* rombar is only used for pci hostdev devices, and bootIndex only
* for disk, network interface, and hostdev devices */
int rombar; /* enum virDomainPciRombarMode */
+ char *romfile;
int bootIndex;
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 3fcd4b1..e4b0431 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1519,15 +1519,15 @@ qemuBuildRomStr(virBufferPtr buf,
virDomainDeviceInfoPtr info,
virBitmapPtr qemuCaps)
{
- if (info->rombar) {
+ if (info->rombar || info->romfile) {
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("rombar is supported only for PCI
devices"));
+ "%s", _("rombar and romfile are supported only
for PCI devices"));
return -1;
}
if (!qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_ROMBAR)) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("rombar not supported in this QEMU
binary"));
+ "%s", _("rombar and romfile not supported in
this QEMU binary"));
return -1;
}
@@ -1541,6 +1541,8 @@ qemuBuildRomStr(virBufferPtr buf,
default:
break;
}
+ if (info->romfile)
+ virBufferAsprintf(buf, ",romfile=%s", info->romfile);
}
return 0;
}
--
1.7.7.5