diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index 34d746dee82f4801253516ecf8a6cbfb6cd69bfc..6959dfef29a0587f0867aa4e361fa91dfc33f393 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -105,6 +105,7 @@
...
<os supported='yes'>
<loader supported='yes'>
+ <value>/usr/share/OVMF/OVMF_CODE.fd</value>
<enum name='type'>
<value>rom</value>
<value>pflash</value>
@@ -122,6 +123,11 @@
For the loader
element, the following can occur:
+ - value
+ - List of known loader paths. Currently this is only used
+ to advertise known locations of OVMF binaries for qemu. Binaries
+ will only be listed if they actually exist on disk.
+
- type
- Whether loader is a typical BIOS (
rom
) or
an UEFI binary (pflash
). This refers to
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index f71e6e15008f29a7309323c710c97e2a756e9926..35d3745dac8769fee9d87868bfe7f15a15a6564e 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -47,6 +47,9 @@
+
+
+
@@ -85,6 +88,14 @@
+
+
+
+
+
+
+
+
@@ -97,11 +108,7 @@
-
-
-
-
-
+
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 5a3c8e71163b49479a0a6fdc85c5dc0e2c11a198..7c5991292cb86e6f60dee68e4efba7c063fc891f 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -47,6 +47,20 @@ static int virDomainCapsOnceInit(void)
VIR_ONCE_GLOBAL_INIT(virDomainCaps)
+static void
+virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values)
+{
+ size_t i;
+
+ if (!values || !values->values)
+ return;
+
+ for (i = 0; i < values->nvalues; i++)
+ VIR_FREE(values->values[i]);
+ VIR_FREE(values->values);
+}
+
+
static void
virDomainCapsDispose(void *obj)
{
@@ -54,6 +68,8 @@ virDomainCapsDispose(void *obj)
VIR_FREE(caps->path);
VIR_FREE(caps->machine);
+
+ virDomainCapsStringValuesFree(&caps->os.loader.values);
}
@@ -156,6 +172,18 @@ virDomainCapsEnumFormat(virBufferPtr buf,
return ret;
}
+
+static void
+virDomainCapsStringValuesFormat(virBufferPtr buf,
+ virDomainCapsStringValuesPtr values)
+{
+ size_t i;
+
+ for (i = 0; i < values->nvalues; i++)
+ virBufferEscapeString(buf, "%s\n", values->values[i]);
+}
+
+
#define FORMAT_PROLOGUE(item) \
do { \
virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \
@@ -185,6 +213,7 @@ virDomainCapsLoaderFormat(virBufferPtr buf,
{
FORMAT_PROLOGUE(loader);
+ virDomainCapsStringValuesFormat(buf, &loader->values);
ENUM_PROCESS(loader, type, virDomainLoaderTypeToString);
ENUM_PROCESS(loader, readonly, virTristateBoolTypeToString);
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 768646b2a8e9bbdaa58b16fcd1a0388ba089c7bd..597ac7593464177d35548a8a78691a560d2dd420 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -37,6 +37,13 @@ struct _virDomainCapsEnum {
unsigned int values; /* Bitmask of values supported in the corresponding enum */
};
+typedef struct _virDomainCapsStringValues virDomainCapsStringValues;
+typedef virDomainCapsStringValues *virDomainCapsStringValuesPtr;
+struct _virDomainCapsStringValues {
+ char **values; /* raw string values */
+ size_t nvalues; /* number of strings */
+};
+
typedef struct _virDomainCapsDevice virDomainCapsDevice;
typedef virDomainCapsDevice *virDomainCapsDevicePtr;
struct _virDomainCapsDevice {
@@ -47,6 +54,7 @@ typedef struct _virDomainCapsLoader virDomainCapsLoader;
typedef virDomainCapsLoader *virDomainCapsLoaderPtr;
struct _virDomainCapsLoader {
virDomainCapsDevice device;
+ virDomainCapsStringValues values; /* Info about values for the element */
virDomainCapsEnum type; /* Info about virDomainLoader */
virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */
};
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c306899d563dbbc874448e8173fa352105e68fab..92468138d929a737afb0c7df6d339782c48dbee1 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3611,10 +3611,30 @@ virQEMUCapsGetDefaultMachine(virQEMUCapsPtr qemuCaps)
static int
virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsLoaderPtr loader,
- virArch arch)
+ virArch arch,
+ virQEMUDriverConfigPtr cfg)
{
+ size_t i;
+
loader->device.supported = true;
+ if (VIR_ALLOC_N(loader->values.values, cfg->nloader) < 0)
+ return -1;
+
+ for (i = 0; i < cfg->nloader; i++) {
+ const char *filename = cfg->loader[i];
+
+ if (!virFileExists(filename)) {
+ VIR_DEBUG("loader filename=%s does not exist", filename);
+ continue;
+ }
+
+ if (VIR_STRDUP(loader->values.values[loader->values.nvalues],
+ filename) < 0)
+ return -1;
+ loader->values.nvalues++;
+ }
+
VIR_DOMAIN_CAPS_ENUM_SET(loader->type,
VIR_DOMAIN_LOADER_TYPE_ROM);
@@ -3636,12 +3656,13 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps,
static int
virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps,
virDomainCapsOSPtr os,
- virArch arch)
+ virArch arch,
+ virQEMUDriverConfigPtr cfg)
{
virDomainCapsLoaderPtr loader = &os->loader;
os->device.supported = true;
- if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch) < 0)
+ if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, loader, arch, cfg) < 0)
return -1;
return 0;
}
@@ -3725,7 +3746,8 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps,
int
virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
- virQEMUCapsPtr qemuCaps)
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverConfigPtr cfg)
{
virDomainCapsOSPtr os = &domCaps->os;
virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
@@ -3734,7 +3756,7 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
domCaps->maxvcpus = maxvcpus;
- if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch) < 0 ||
+ if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, domCaps->arch, cfg) < 0 ||
virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, disk) < 0 ||
virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0)
return -1;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 828bba371926749ae54fad31a968961842e9a8d8..cf69e5953c107ac8f6cadce4a39ab02c23900f7b 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -324,7 +324,12 @@ int virQEMUCapsInitGuestFromBinary(virCapsPtr caps,
virQEMUCapsPtr kvmbinCaps,
virArch guestarch);
+/* Forward declaration */
+typedef struct _virQEMUDriverConfig virQEMUDriverConfig;
+typedef virQEMUDriverConfig *virQEMUDriverConfigPtr;
+
int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps,
- virQEMUCapsPtr qemuCaps);
+ virQEMUCapsPtr qemuCaps,
+ virQEMUDriverConfigPtr cfg);
#endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4fe5909cc41e82c6140791168c5f35922ff2af88..822a4ebc6c8e444ab8a0d529bd8fa4976450455a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17285,12 +17285,15 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
int virttype; /* virDomainVirtType */
virDomainCapsPtr domCaps = NULL;
int arch = virArchFromHost(); /* virArch */
+ virQEMUDriverConfigPtr cfg = NULL;
virCheckFlags(0, ret);
if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
return ret;
+ cfg = virQEMUDriverGetConfig(driver);
+
if (qemuHostdevHostSupportsPassthroughLegacy())
virttype = VIR_DOMAIN_VIRT_KVM;
else
@@ -17357,11 +17360,12 @@ qemuConnectGetDomainCapabilities(virConnectPtr conn,
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
goto cleanup;
- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
goto cleanup;
ret = virDomainCapsFormat(domCaps);
cleanup:
+ virObjectUnref(cfg);
virObjectUnref(domCaps);
virObjectUnref(qemuCaps);
return ret;
diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml
index 97227726e273f4d3e4ef892470cfa7ffadb1fb90..96202bca6d0bfdd0033b1d72995b648b0d76c359 100644
--- a/tests/domaincapsschemadata/domaincaps-full.xml
+++ b/tests/domaincapsschemadata/domaincaps-full.xml
@@ -6,6 +6,8 @@
+ /foo/bar
+ /tmp/my_path
rom
pflash
diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
index 568cecbe9edbc76fdd279486a317bba500aaacdf..346ef65a69b7b723886581d958c51a5cae05c7de 100644
--- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
+++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml
@@ -5,6 +5,7 @@
x86_64
+ /usr/share/OVMF/OVMF_CODE.fd
rom
pflash
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index 0c4b09ff82fcc032ad11d096c5adb2e16bdeead0..85439632b185e5c11bd2e8c8c1da0ec77d883a07 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -34,6 +34,27 @@ typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps,
#define SET_ALL_BITS(x) \
memset(&(x.values), 0xff, sizeof(x.values))
+static int ATTRIBUTE_SENTINEL
+fillStringValues(virDomainCapsStringValuesPtr values, ...)
+{
+ int ret = 0;
+ va_list list;
+ const char *str;
+
+ va_start(list, values);
+ while ((str = va_arg(list, const char *))) {
+ if (VIR_REALLOC_N(values->values, values->nvalues + 1) < 0 ||
+ VIR_STRDUP(values->values[values->nvalues], str) < 0) {
+ ret = -1;
+ break;
+ }
+ values->nvalues++;
+ }
+ va_end(list);
+
+ return ret;
+}
+
static int
fillAll(virDomainCapsPtr domCaps,
void *opaque ATTRIBUTE_UNUSED)
@@ -49,6 +70,11 @@ fillAll(virDomainCapsPtr domCaps,
loader->device.supported = true;
SET_ALL_BITS(loader->type);
SET_ALL_BITS(loader->readonly);
+ if (fillStringValues(&loader->values,
+ "/foo/bar",
+ "/tmp/my_path",
+ NULL) < 0)
+ return -1;
disk->device.supported = true;
SET_ALL_BITS(disk->diskDevice);
@@ -66,13 +92,21 @@ fillAll(virDomainCapsPtr domCaps,
#ifdef WITH_QEMU
# include "testutilsqemu.h"
+
+struct fillQemuCapsData {
+ virQEMUCapsPtr qemuCaps;
+ virQEMUDriverConfigPtr cfg;
+};
+
static int
fillQemuCaps(virDomainCapsPtr domCaps,
void *opaque)
{
- virQEMUCapsPtr qemuCaps = (virQEMUCapsPtr) opaque;
+ struct fillQemuCapsData *data = (struct fillQemuCapsData *) opaque;
+ virQEMUCapsPtr qemuCaps = data->qemuCaps;
+ virQEMUDriverConfigPtr cfg = data->cfg;
- if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps) < 0)
+ if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps, cfg) < 0)
return -1;
/* The function above tries to query host's KVM & VFIO capabilities by
@@ -97,7 +131,7 @@ buildVirDomainCaps(const char *emulatorbin,
virDomainCapsFill fillFunc,
void *opaque)
{
- virDomainCapsPtr domCaps;
+ virDomainCapsPtr domCaps, ret = NULL;
if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, type)))
goto cleanup;
@@ -107,8 +141,9 @@ buildVirDomainCaps(const char *emulatorbin,
domCaps = NULL;
}
+ ret = domCaps;
cleanup:
- return domCaps;
+ return ret;
}
struct test_virDomainCapsFormatData {
@@ -182,13 +217,16 @@ mymain(void)
#ifdef WITH_QEMU
+ virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false);
+
# define DO_TEST_QEMU(Filename, QemuCapsFile, Emulatorbin, Machine, Arch, Type, ...) \
do { \
const char *capsPath = abs_srcdir "/qemucapabilitiesdata/" QemuCapsFile ".caps"; \
virQEMUCapsPtr qemuCaps = qemuTestParseCapabilities(capsPath); \
+ struct fillQemuCapsData fillData = {.qemuCaps = qemuCaps, .cfg = cfg}; \
struct test_virDomainCapsFormatData data = {.filename = Filename, \
.emulatorbin = Emulatorbin, .machine = Machine, .arch = Arch, \
- .type = Type, .fillFunc = fillQemuCaps, .opaque = qemuCaps}; \
+ .type = Type, .fillFunc = fillQemuCaps, .opaque = &fillData}; \
if (!qemuCaps) { \
fprintf(stderr, "Unable to build qemu caps from %s\n", capsPath); \
ret = -1; \
@@ -199,6 +237,7 @@ mymain(void)
DO_TEST_QEMU("qemu_1.6.50-1", "caps_1.6.50-1", "/usr/bin/qemu-system-x86_64",
"pc-1.2", VIR_ARCH_X86_64, VIR_DOMAIN_VIRT_KVM);
+ virObjectUnref(cfg);
#endif /* WITH_QEMU */
return ret;