On Tue, Apr 21, 2026 at 11:00:21 +0530, Surya Gupta via Devel wrote:
Some VMware guests specify NVRAM storage using the 'nvram' parameter. If found, parse it and store it in the domain's os.loader.nvram field, which gets formatted as:
<os> <type arch='x86_64'>hvm</type> <nvram>[datastore] directory/dokuwiki.nvram</nvram> </os>
The NVRAM path uses the same transformation functions as disk paths (ctx->parseFileName and ctx->formatFileName) to ensure consistent handling of datastore-qualified paths. The NVRAM is stored as a virStorageSource with type VIR_STORAGE_TYPE_FILE to ensure compatibility with libvirt's existing firmware handling infrastructure.
This issue isn't public (insn't accessible without being logged in). Do not mention it in public commit messages.
Signed-off-by: Surya Gupta <surygupt@redhat.com> --- src/vmx/vmx.c | 32 ++++++++++++++++++++++++ tests/vmx2xmldata/case-insensitive-1.xml | 1 + tests/vmx2xmldata/case-insensitive-2.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-1.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-10.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-11.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-12.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-13.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-14.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-15.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-16.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-17.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-2.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-3.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-4.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-5.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-6.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-7.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-8.xml | 1 + tests/vmx2xmldata/esx-in-the-wild-9.xml | 1 + tests/vmx2xmldata/gsx-in-the-wild-1.xml | 1 + tests/vmx2xmldata/gsx-in-the-wild-2.xml | 1 + tests/vmx2xmldata/gsx-in-the-wild-3.xml | 1 + tests/vmx2xmldata/gsx-in-the-wild-4.xml | 1 + 24 files changed, 55 insertions(+)
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c index 57dfd57cfc..c42b030dd6 100644 --- a/src/vmx/vmx.c +++ b/src/vmx/vmx.c @@ -1415,6 +1415,7 @@ virVMXParseConfig(virVMXContext *ctx, long long coresPerSocket = 0; virCPUDef *cpu = NULL; char *firmware = NULL; + char *nvram = NULL;
[1]
size_t saved_ndisks = 0;
if (ctx->parseFileName == NULL) { @@ -2022,6 +2023,26 @@ virVMXParseConfig(virVMXContext *ctx, VIR_TRISTATE_BOOL_YES; }
+ /* vmx:nvram */ + if (virVMXGetConfigString(conf, "nvram", &nvram, true) < 0) { + goto cleanup; + } + + if (nvram != NULL) { + g_autoptr(virStorageSource) n = virStorageSourceNew();
You use 'autoptr' here, why not declare the 'nvram' string [1] as: g_autofree char *nvram = NULL ?
+ char *tmp = NULL; + + if (!def->os.loader) { + def->os.loader = virDomainLoaderDefNew();
Can this ever be already allocated? [2]
+ } + + n->type = VIR_STORAGE_TYPE_FILE; + if (ctx->parseFileName(nvram, ctx->opaque, &tmp, false) < 0)
n->path is also a 'char *' you can use it instead of the extra 'tmp' variable ...
+ goto cleanup; + n->path = tmp;
... if you otherwise directly assign it.
+ def->os.loader->nvram = g_steal_pointer(&n);
[2] I'm asking because this then could overwrite existing value here leaking the original.
+ } + if (virDomainDefPostParse(def, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, xmlopt, NULL) < 0) goto cleanup; @@ -2035,6 +2056,7 @@ virVMXParseConfig(virVMXContext *ctx, VIR_FREE(guestOS); virCPUDefFree(cpu); VIR_FREE(firmware); + VIR_FREE(nvram);
this can be skipped if autofree is used.