[libvirt] [PATCH 2/2] qemu_firmware: Try to autofill for old style UEFI specification
Cole Robinson
crobinso at redhat.com
Wed Dec 18 22:50:36 UTC 2019
On 12/17/19 12:25 PM, Michal Privoznik wrote:
> While we discourage people to use the old style of specifying
> UEFI for their domains (the old style is putting path to the FW
> image under /domain/os/loader/ whilst the new one is using
> /domain/os/@firmware), some applications might have not adopted
> yet. They still rely on libvirt autofilling NVRAM path and
> figuring out NVRAM template when using the old way (notably
> virt-install does this). And in a way they are right. However,
> since we really want distro maintainers to leave
> --with-loader-nvram configure option and rely on JSON
> descriptors, we need to implement autofilling of NVRAM template
> for the old way too.
>
> Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1782778
> RHEL: https://bugzilla.redhat.com/show_bug.cgi?id=1776949
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
So this uses firmware.json to info to turn this input XML
<loader readonly="yes" type="pflash">/CODE.fd</loader>
into this output XML
<loader readonly="yes" type="pflash">/CODE.fd</loader>
<nvram template="/VARS.fd"/>
independent of --with-loader-nvram, which was previously used to handle
that case. And virt-install still uses this method by default. Is that
correct?
I'm surprised we don't have an an XML test case to cover this. How hard
is it to add?
> src/qemu/qemu_firmware.c | 82 +++++++++++++++++++++++++++++++++++-----
> 1 file changed, 72 insertions(+), 10 deletions(-)
>
> diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
> index 96058c9b45..a31bde5d04 100644
> --- a/src/qemu/qemu_firmware.c
> +++ b/src/qemu/qemu_firmware.c
> @@ -935,17 +935,53 @@ qemuFirmwareMatchDomain(const virDomainDef *def,
> const qemuFirmware *fw,
> const char *path)
> {
> - size_t i;
> + qemuFirmwareOSInterface want = QEMU_FIRMWARE_OS_INTERFACE_NONE;
> bool supportsS3 = false;
> bool supportsS4 = false;
> bool requiresSMM = false;
> bool supportsSEV = false;
> + size_t i;
> +
> + switch (def->os.firmware) {
> + case VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS:
> + want = QEMU_FIRMWARE_OS_INTERFACE_BIOS;
> + break;
> + case VIR_DOMAIN_OS_DEF_FIRMWARE_EFI:
> + want = QEMU_FIRMWARE_OS_INTERFACE_UEFI;
> + break;
> + case VIR_DOMAIN_OS_DEF_FIRMWARE_NONE:
> + case VIR_DOMAIN_OS_DEF_FIRMWARE_LAST:
> + break;
> + }
> +
This is a refactoring that could have been done first. It's hard to
digest all the details in this patch.
> + if (want == QEMU_FIRMWARE_OS_INTERFACE_NONE &&
> + def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE &&
> + def->os.loader) {
> + switch (def->os.loader->type) {
> + case VIR_DOMAIN_LOADER_TYPE_ROM:
> + want = QEMU_FIRMWARE_OS_INTERFACE_BIOS;
> + break;
> + case VIR_DOMAIN_LOADER_TYPE_PFLASH:
> + want = QEMU_FIRMWARE_OS_INTERFACE_UEFI;
> + break;
> + case VIR_DOMAIN_LOADER_TYPE_NONE:
> + case VIR_DOMAIN_LOADER_TYPE_LAST:
> + break;
> + }
> +
And it might be overkill but it would help readability if these switches
were moved to their own functions, like
qemuFirmwareTypeFromInterfaceType or similar
> + if (fw->mapping.device != QEMU_FIRMWARE_DEVICE_FLASH ||
> + STRNEQ(def->os.loader->path, fw->mapping.data.flash.executable.filename)) {
> + VIR_DEBUG("Not matching FW interface %s or loader "
> + "path '%s' for user provided path '%s'",
> + qemuFirmwareDeviceTypeToString(fw->mapping.device),
> + fw->mapping.data.flash.executable.filename,
> + def->os.loader->path);
> + return false;
> + }
> + }
>
> for (i = 0; i < fw->ninterfaces; i++) {
> - if ((def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS &&
> - fw->interfaces[i] == QEMU_FIRMWARE_OS_INTERFACE_BIOS) ||
> - (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_EFI &&
> - fw->interfaces[i] == QEMU_FIRMWARE_OS_INTERFACE_UEFI))
> + if (fw->interfaces[i] == want)
> break;
> }
>
> @@ -1211,14 +1247,33 @@ qemuFirmwareFillDomain(virQEMUDriverPtr driver,
> qemuFirmwarePtr *firmwares = NULL;
> ssize_t nfirmwares = 0;
> const qemuFirmware *theone = NULL;
> + bool needResult = true;
> size_t i;
> int ret = -1;
>
> if (!(flags & VIR_QEMU_PROCESS_START_NEW))
> return 0;
>
> - if (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE)
> - return 0;
> + /* Fill in FW paths if either os.firmware is enabled, or
> + * loader path was provided with no nvram varstore. */
> + if (def->os.firmware == VIR_DOMAIN_OS_DEF_FIRMWARE_NONE) {
> + /* This is horrific check, but loosely said, if UEFI
> + * image was provided by the old method (by specifying
> + * its path in domain XML) but no template for NVRAM was
> + * specified ... */
> + if (!(def->os.loader &&
> + def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH &&
> + def->os.loader->path &&
> + def->os.loader->readonly == VIR_TRISTATE_BOOL_YES &&
> + !def->os.loader->templt &&
> + def->os.loader->nvram &&
> + !virFileExists(def->os.loader->nvram)))
> + return 0;
> +
This loader checking logic is duplicated in a few places already, see
all 4 of 5 PFLASH uses in qemu_domain.c and similar checks in xen code.
IMO it should be factored out first
- Cole
More information about the libvir-list
mailing list