提交 9c0d73bf 编写于 作者: M Michal Privoznik

qemu_firmware: Introduce qemuFirmwareGetSupported

The point of this API is to fetch all FW descriptors, parse them
and return list of supported interfaces and SMM feature for given
combination of machine type and guest architecture.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Acked-by: NLaszlo Ersek <lersek@redhat.com>
上级 2337309e
...@@ -1346,7 +1346,8 @@ qemuFirmwareFetchParsedConfigs(bool privileged, ...@@ -1346,7 +1346,8 @@ qemuFirmwareFetchParsedConfigs(bool privileged,
} }
VIR_STEAL_PTR(*firmwaresRet, firmwares); VIR_STEAL_PTR(*firmwaresRet, firmwares);
VIR_STEAL_PTR(*pathsRet, paths); if (pathsRet)
VIR_STEAL_PTR(*pathsRet, paths);
return npaths; return npaths;
error: error:
...@@ -1412,3 +1413,71 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver, ...@@ -1412,3 +1413,71 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver,
VIR_FREE(firmwares); VIR_FREE(firmwares);
return ret; return ret;
} }
int
qemuFirmwareGetSupported(const char *machine,
virArch arch,
bool privileged,
uint64_t *supported,
bool *secure)
{
qemuFirmwarePtr *firmwares = NULL;
ssize_t nfirmwares = 0;
size_t i;
*supported = VIR_DOMAIN_OS_DEF_FIRMWARE_NONE;
*secure = false;
if ((nfirmwares = qemuFirmwareFetchParsedConfigs(privileged,
&firmwares, NULL)) < 0)
return -1;
for (i = 0; i < nfirmwares; i++) {
qemuFirmwarePtr fw = firmwares[i];
size_t j;
if (!qemuFirmwareMatchesMachineArch(fw, machine, arch))
continue;
for (j = 0; j < fw->ninterfaces; j++) {
switch (fw->interfaces[j]) {
case QEMU_FIRMWARE_OS_INTERFACE_UEFI:
*supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_EFI;
break;
case QEMU_FIRMWARE_OS_INTERFACE_BIOS:
*supported |= 1ULL << VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS;
break;
case QEMU_FIRMWARE_OS_INTERFACE_NONE:
case QEMU_FIRMWARE_OS_INTERFACE_OPENFIRMWARE:
case QEMU_FIRMWARE_OS_INTERFACE_UBOOT:
case QEMU_FIRMWARE_OS_INTERFACE_LAST:
default:
break;
}
}
for (j = 0; j < fw->nfeatures; j++) {
switch (fw->features[j]) {
case QEMU_FIRMWARE_FEATURE_REQUIRES_SMM:
*secure = true;
break;
case QEMU_FIRMWARE_FEATURE_NONE:
case QEMU_FIRMWARE_FEATURE_ACPI_S3:
case QEMU_FIRMWARE_FEATURE_ACPI_S4:
case QEMU_FIRMWARE_FEATURE_AMD_SEV:
case QEMU_FIRMWARE_FEATURE_ENROLLED_KEYS:
case QEMU_FIRMWARE_FEATURE_SECURE_BOOT:
case QEMU_FIRMWARE_FEATURE_VERBOSE_DYNAMIC:
case QEMU_FIRMWARE_FEATURE_VERBOSE_STATIC:
case QEMU_FIRMWARE_FEATURE_LAST:
break;
}
}
}
for (i = 0; i < nfirmwares; i++)
qemuFirmwareFree(firmwares[i]);
VIR_FREE(firmwares);
return 0;
}
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
# include "domain_conf.h" # include "domain_conf.h"
# include "qemu_conf.h" # include "qemu_conf.h"
# include "virautoclean.h" # include "virautoclean.h"
# include "virarch.h"
typedef struct _qemuFirmware qemuFirmware; typedef struct _qemuFirmware qemuFirmware;
typedef qemuFirmware *qemuFirmwarePtr; typedef qemuFirmware *qemuFirmwarePtr;
...@@ -48,4 +49,13 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver, ...@@ -48,4 +49,13 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
unsigned int flags); unsigned int flags);
int
qemuFirmwareGetSupported(const char *machine,
virArch arch,
bool privileged,
uint64_t *supported,
bool *secure);
verify(VIR_DOMAIN_OS_DEF_FIRMWARE_LAST <= 64);
#endif /* LIBVIRT_QEMU_FIRMWARE_H */ #endif /* LIBVIRT_QEMU_FIRMWARE_H */
#include <config.h> #include <config.h>
#include <inttypes.h>
#include "testutils.h" #include "testutils.h"
#include "virfilewrapper.h" #include "virfilewrapper.h"
#include "qemu/qemu_firmware.h" #include "qemu/qemu_firmware.h"
...@@ -99,6 +101,53 @@ testFWPrecedence(const void *opaque ATTRIBUTE_UNUSED) ...@@ -99,6 +101,53 @@ testFWPrecedence(const void *opaque ATTRIBUTE_UNUSED)
} }
struct supportedData {
const char *machine;
virArch arch;
bool secure;
unsigned int *interfaces;
size_t ninterfaces;
};
static int
testSupportedFW(const void *opaque)
{
const struct supportedData *data = opaque;
uint64_t actualInterfaces;
uint64_t expectedInterfaces = 0;
bool actualSecure;
size_t i;
for (i = 0; i < data->ninterfaces; i++)
expectedInterfaces |= 1ULL << data->interfaces[i];
if (qemuFirmwareGetSupported(data->machine, data->arch, false,
&actualInterfaces, &actualSecure) < 0) {
fprintf(stderr, "Unable to get list of supported interfaces\n");
return -1;
}
if (actualInterfaces != expectedInterfaces) {
fprintf(stderr,
"Mismatch in supported interfaces. "
"Expected 0x%" PRIx64 " got 0x%" PRIx64 "\n",
expectedInterfaces, actualInterfaces);
return -1;
}
if (actualSecure != data->secure) {
fprintf(stderr,
"Mismatch in SMM requirement/support. "
"Expected %d got %d\n",
data->secure, actualSecure);
return -1;
}
return 0;
}
static int static int
mymain(void) mymain(void)
{ {
...@@ -127,6 +176,29 @@ mymain(void) ...@@ -127,6 +176,29 @@ mymain(void)
if (virTestRun("QEMU FW precedence test", testFWPrecedence, NULL) < 0) if (virTestRun("QEMU FW precedence test", testFWPrecedence, NULL) < 0)
ret = -1; ret = -1;
#define DO_SUPPORTED_TEST(machine, arch, secure, ...) \
do { \
unsigned int interfaces[] = {__VA_ARGS__}; \
struct supportedData data = {machine, arch, secure, \
interfaces, ARRAY_CARDINALITY(interfaces)}; \
if (virTestRun("QEMU FW SUPPORTED " machine " " #arch, \
testSupportedFW, &data) < 0) \
ret = -1; \
} while (0)
DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_X86_64, false,
VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS,
VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
DO_SUPPORTED_TEST("pc-i440fx-3.1", VIR_ARCH_I686, false,
VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_X86_64, true,
VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS,
VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
DO_SUPPORTED_TEST("pc-q35-3.1", VIR_ARCH_I686, false,
VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS);
DO_SUPPORTED_TEST("virt-3.1", VIR_ARCH_AARCH64, false,
VIR_DOMAIN_OS_DEF_FIRMWARE_EFI);
virFileWrapperClearPrefixes(); virFileWrapperClearPrefixes();
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册