From nobody Sun Feb 8 14:57:50 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 155126192977135.50418556988279; Wed, 27 Feb 2019 02:05:29 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 889BD7BDC2; Wed, 27 Feb 2019 10:05:27 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5E49C5D6B6; Wed, 27 Feb 2019 10:05:27 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 1290C181A010; Wed, 27 Feb 2019 10:05:27 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x1RA5HJK032279 for ; Wed, 27 Feb 2019 05:05:17 -0500 Received: by smtp.corp.redhat.com (Postfix) id B740B1001DC6; Wed, 27 Feb 2019 10:05:17 +0000 (UTC) Received: from moe.brq.redhat.com (unknown [10.43.2.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id 133991001938; Wed, 27 Feb 2019 10:05:16 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 27 Feb 2019 11:04:38 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com Cc: lersek@redhat.com Subject: [libvirt] [PATCH v1 06/15] conf: Introduce firmware attribute to X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 27 Feb 2019 10:05:28 +0000 (UTC) Content-Type: text/plain; charset="utf-8" The idea is that using this attribute users enable libvirt to automagically select firmware image for their domain. For instance: hvm hvm (The automagic of selecting firmware image will be described in later commits.) Accepted values are 'bios' and 'efi' to let libvirt select corresponding type of firmware. I know it is a good sign to introduce xml2xml test case when changing XML config parser but that will have to come later. Firmware auto selection is not enabled for any driver just yet so any xml2xml test would fail right away. Signed-off-by: Michal Privoznik --- docs/formatdomain.html.in | 22 +++++++++- docs/schemas/domaincommon.rng | 8 ++++ src/conf/domain_conf.c | 75 ++++++++++++++++++++++++++++------- src/conf/domain_conf.h | 12 ++++++ src/libvirt_private.syms | 2 + 5 files changed, 103 insertions(+), 16 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b848e535e6..45f7af0e8b 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -128,7 +128,7 @@ =20
 ...
-<os>
+<os firmware=3D'uefi'>
   <type>hvm</type>
   <loader readonly=3D'yes' secure=3D'no' type=3D'rom'>/usr/lib/xen/b=
oot/hvmloader</loader>
   <nvram template=3D'/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/=
nvram/guest_VARS.fd</nvram>
@@ -141,6 +141,26 @@
 ...
=20
+
firmware
+
The firmware attribute allows management + applications to automatically fill <loader/> + and <nvram/> elements and possibly enable + some features required by selected firmware. Accepted values are + bios and efi.
+ The selection process scans for files describing installed + firmware images in specified location and uses the most specific + one which fulfils domain requirements. The locations in order of + preference (from generic to most specific one) are: +
    +
  • /usr/share/qemu/firmware
  • +
  • /etc/qemu/firmware
  • +
  • $XDG_CONFIG_HOME/qemu/firmware
  • +
+ For more information refer to firmware metadata specification as + described in docs/interop/firmware.json in QEMU + repository. Regular users do not need to bother. + Since 5.2.0 (QEMU and KVM only) +
type
The content of the type element specifies the type of operating system to be booted in the virtual machine. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index bebe39de76..7b858f2685 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -256,6 +256,14 @@ + + + + bios + efi + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b436b91c66..0ca923b505 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1033,6 +1033,13 @@ VIR_ENUM_IMPL(virDomainHPTResizing, "required", ); =20 +VIR_ENUM_IMPL(virDomainOsDefFirmware, + VIR_DOMAIN_OS_DEF_FIRMWARE_LAST, + "none", + "bios", + "efi", +); + /* Internal mapping: subset of block job types that can be present in * XML (remaining types are not two-phase). */ VIR_ENUM_DECL(virDomainBlockJob); @@ -6582,14 +6589,23 @@ virDomainDefMemtuneValidate(const virDomainDef *def) =20 =20 static int -virDomainDefOSValidate(const virDomainDef *def) +virDomainDefOSValidate(const virDomainDef *def, + virDomainXMLOptionPtr xmlopt) { if (!def->os.loader) return 0; =20 - if (!def->os.loader->path) { + if (def->os.firmware && + !(xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT))= { virReportError(VIR_ERR_XML_DETAIL, "%s", - _("no loader path specified")); + _("firmware auto selection not implemented for this= driver")); + return -1; + } + + if (!def->os.loader->path && + def->os.firmware =3D=3D VIR_DOMAIN_OS_DEF_FIRMWARE_NONE) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("no loader path specified and firmware auto selec= tion disabled")); return -1; } =20 @@ -6598,7 +6614,8 @@ virDomainDefOSValidate(const virDomainDef *def) =20 =20 static int -virDomainDefValidateInternal(const virDomainDef *def) +virDomainDefValidateInternal(const virDomainDef *def, + virDomainXMLOptionPtr xmlopt) { if (virDomainDefCheckDuplicateDiskInfo(def) < 0) return -1; @@ -6635,7 +6652,7 @@ virDomainDefValidateInternal(const virDomainDef *def) if (virDomainDefMemtuneValidate(def) < 0) return -1; =20 - if (virDomainDefOSValidate(def) < 0) + if (virDomainDefOSValidate(def, xmlopt) < 0) return -1; =20 return 0; @@ -6686,7 +6703,7 @@ virDomainDefValidate(virDomainDefPtr def, &data) < 0) return -1; =20 - if (virDomainDefValidateInternal(def) < 0) + if (virDomainDefValidateInternal(def, xmlopt) < 0) return -1; =20 return 0; @@ -18692,20 +18709,23 @@ virDomainDefMaybeAddHostdevSCSIcontroller(virDoma= inDefPtr def) =20 static int virDomainLoaderDefParseXML(xmlNodePtr node, - virDomainLoaderDefPtr loader) + virDomainLoaderDefPtr loader, + bool fwAutoSelect) { int ret =3D -1; char *readonly_str =3D NULL; char *secure_str =3D NULL; char *type_str =3D NULL; =20 - readonly_str =3D virXMLPropString(node, "readonly"); secure_str =3D virXMLPropString(node, "secure"); - type_str =3D virXMLPropString(node, "type"); - loader->path =3D (char *) xmlNodeGetContent(node); =20 - if (STREQ_NULLABLE(loader->path, "")) - VIR_FREE(loader->path); + if (!fwAutoSelect) { + readonly_str =3D virXMLPropString(node, "readonly"); + type_str =3D virXMLPropString(node, "type"); + loader->path =3D (char *) xmlNodeGetContent(node); + if (STREQ_NULLABLE(loader->path, "")) + VIR_FREE(loader->path); + } =20 if (readonly_str && (loader->readonly =3D virTristateBoolTypeFromString(readonly_str))= <=3D 0) { @@ -19120,6 +19140,7 @@ virDomainDefParseBootOptions(virDomainDefPtr def, def->os.type =3D=3D VIR_DOMAIN_OSTYPE_XENPVH || def->os.type =3D=3D VIR_DOMAIN_OSTYPE_HVM || def->os.type =3D=3D VIR_DOMAIN_OSTYPE_UML) { + VIR_AUTOFREE(char *) firmware =3D NULL; xmlNodePtr loader_node; =20 def->os.kernel =3D virXPathString("string(./os/kernel[1])", ctxt); @@ -19127,15 +19148,35 @@ virDomainDefParseBootOptions(virDomainDefPtr def, def->os.cmdline =3D virXPathString("string(./os/cmdline[1])", ctxt= ); def->os.dtb =3D virXPathString("string(./os/dtb[1])", ctxt); def->os.root =3D virXPathString("string(./os/root[1])", ctxt); + + if (def->os.type =3D=3D VIR_DOMAIN_OSTYPE_HVM && + (firmware =3D virXPathString("string(./os/@firmware)", ctxt)))= { + int fw =3D virDomainOsDefFirmwareTypeFromString(firmware); + + if (fw <=3D 0) { + virReportError(VIR_ERR_XML_ERROR, + _("unknown firmware value %s"), + firmware); + goto error; + } + + def->os.firmware =3D fw; + } + if ((loader_node =3D virXPathNode("./os/loader[1]", ctxt))) { + const bool fwAutoSelect =3D def->os.firmware !=3D VIR_DOMAIN_O= S_DEF_FIRMWARE_NONE; + if (VIR_ALLOC(def->os.loader) < 0) goto error; =20 - if (virDomainLoaderDefParseXML(loader_node, def->os.loader) < = 0) + if (virDomainLoaderDefParseXML(loader_node, + def->os.loader, + fwAutoSelect) < 0) goto error; =20 def->os.loader->nvram =3D virXPathString("string(./os/nvram[1]= )", ctxt); - def->os.loader->templt =3D virXPathString("string(./os/nvram[1= ]/@template)", ctxt); + if (!fwAutoSelect) + def->os.loader->templt =3D virXPathString("string(./os/nvr= am[1]/@template)", ctxt); } } =20 @@ -28459,7 +28500,11 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->os.bootloaderArgs); } =20 - virBufferAddLit(buf, "\n"); + virBufferAddLit(buf, "os.firmware) + virBufferAsprintf(buf, " firmware=3D'%s'", + virDomainOsDefFirmwareTypeToString(def->os.firmw= are)); + virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); virBufferAddLit(buf, "os.arch) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 4e8c02b5e3..c1e7845cf8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1950,10 +1950,21 @@ struct _virDomainOSEnv { char *value; }; =20 +typedef enum { + VIR_DOMAIN_OS_DEF_FIRMWARE_NONE =3D 0, + VIR_DOMAIN_OS_DEF_FIRMWARE_BIOS, + VIR_DOMAIN_OS_DEF_FIRMWARE_EFI, + + VIR_DOMAIN_OS_DEF_FIRMWARE_LAST +} virDomainOsDefFirmware; + +VIR_ENUM_DECL(virDomainOsDefFirmware); + typedef struct _virDomainOSDef virDomainOSDef; typedef virDomainOSDef *virDomainOSDefPtr; struct _virDomainOSDef { int type; + virDomainOsDefFirmware firmware; virArch arch; char *machine; size_t nBootDevs; @@ -2670,6 +2681,7 @@ typedef enum { VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS =3D (1 << 4), VIR_DOMAIN_DEF_FEATURE_USER_ALIAS =3D (1 << 5), VIR_DOMAIN_DEF_FEATURE_NO_BOOT_ORDER =3D (1 << 6), + VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT =3D (1 << 7), } virDomainDefFeatures; =20 =20 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 038a744981..fdd67a7fde 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -504,6 +504,8 @@ virDomainObjTaint; virDomainObjUpdateModificationImpact; virDomainObjWait; virDomainObjWaitUntil; +virDomainOsDefFirmwareTypeFromString; +virDomainOsDefFirmwareTypeToString; virDomainOSTypeFromString; virDomainOSTypeToString; virDomainParseMemory; --=20 2.19.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list