1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-20 06:50:22 +03:00

conf: introduce support for multiple ACPI tables

Currently we parse

   <os>
     <acpi>
       <table type="slic">...path...</table>
     </acpi>
   </os>

into a flat 'char *slic_table' field which is rather an anti-pattern
as it has special cased a single attribute type.

This rewrites the internal design to permit multiple table types to
be parsed, should we add more in future. Each type is currently
permitted to only appear once.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2025-02-17 16:30:07 +00:00
parent 92de6563c6
commit 55f48d3852
9 changed files with 134 additions and 53 deletions

View File

@ -1457,6 +1457,11 @@ VIR_ENUM_IMPL(virDomainOsDefFirmwareFeature,
"secure-boot",
);
VIR_ENUM_IMPL(virDomainOsACPITable,
VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST,
"slic",
);
VIR_ENUM_IMPL(virDomainCFPC,
VIR_DOMAIN_CFPC_LAST,
"none",
@ -3899,6 +3904,15 @@ virDomainSecDefFree(virDomainSecDef *def)
g_free(def);
}
void virDomainOSACPITableDefFree(virDomainOSACPITableDef *def)
{
if (!def)
return;
g_free(def->path);
g_free(def);
}
static void
virDomainOSDefClear(virDomainOSDef *os)
{
@ -3924,7 +3938,9 @@ virDomainOSDefClear(virDomainOSDef *os)
g_free(os->cmdline);
g_free(os->dtb);
g_free(os->root);
g_free(os->slic_table);
for (i = 0; i < os->nacpiTables; i++)
virDomainOSACPITableDefFree(os->acpiTables[i]);
g_free(os->acpiTables);
virDomainLoaderDefFree(os->loader);
g_free(os->bootloader);
g_free(os->bootloaderArgs);
@ -17858,40 +17874,57 @@ virDomainDefParseBootAcpiOptions(virDomainDef *def,
int n;
g_autofree xmlNodePtr *nodes = NULL;
g_autofree char *tmp = NULL;
size_t ntables = 0;
virDomainOSACPITableDef **tables = NULL;
size_t i;
if ((n = virXPathNodeSet("./os/acpi/table", ctxt, &nodes)) < 0)
return -1;
if (n > 1) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Only one acpi table is supported"));
return -1;
}
if (n == 0)
return 0;
if (n == 1) {
tmp = virXMLPropString(nodes[0], "type");
tables = g_new0(virDomainOSACPITableDef *, n);
for (i = 0; i < n; i++) {
g_autofree char *path = virXMLNodeContentString(nodes[i]);
virDomainOsACPITable type;
size_t j;
if (!tmp) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("Missing acpi table type"));
return -1;
if (!path)
goto error;
if (virXMLPropEnum(nodes[i], "type",
virDomainOsACPITableTypeFromString,
VIR_XML_PROP_REQUIRED,
&type) < 0)
goto error;
for (j = 0; j < i; j++) {
if (tables[j]->type == type) {
virReportError(VIR_ERR_XML_ERROR,
_("ACPI table type '%1$s' may only appear once"),
virDomainOsACPITableTypeToString(type));
goto error;
}
}
if (STREQ_NULLABLE(tmp, "slic")) {
VIR_FREE(tmp);
if (!(tmp = virXMLNodeContentString(nodes[0])))
return -1;
def->os.slic_table = virFileSanitizePath(tmp);
} else {
virReportError(VIR_ERR_XML_ERROR,
_("Unknown acpi table type: %1$s"),
tmp);
return -1;
}
tables[ntables] = g_new0(virDomainOSACPITableDef, 1);
tables[ntables]->type = type;
tables[ntables]->path = virFileSanitizePath(path);
ntables++;
}
def->os.nacpiTables = ntables;
def->os.acpiTables = tables;
return 0;
error:
for (i = 0; i < ntables; i++) {
virDomainOSACPITableDefFree(tables[i]);
}
g_free(tables);
return -1;
}
@ -28418,11 +28451,16 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
def->os.dtb);
virBufferEscapeString(buf, "<root>%s</root>\n",
def->os.root);
if (def->os.slic_table) {
if (def->os.nacpiTables) {
virBufferAddLit(buf, "<acpi>\n");
virBufferAdjustIndent(buf, 2);
virBufferEscapeString(buf, "<table type='slic'>%s</table>\n",
def->os.slic_table);
for (i = 0; i < def->os.nacpiTables; i++) {
virBufferAsprintf(buf, "<table type='%s'>",
virDomainOsACPITableTypeToString(def->os.acpiTables[i]->type));
virBufferEscapeString(buf, "%s</table>\n",
def->os.acpiTables[i]->path);
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</acpi>\n");
}

View File

@ -2481,6 +2481,24 @@ typedef enum {
VIR_ENUM_DECL(virDomainOsDefFirmwareFeature);
typedef enum {
VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC,
VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST
} virDomainOsACPITable;
VIR_ENUM_DECL(virDomainOsACPITable);
struct _virDomainOSACPITableDef {
virDomainOsACPITable type;
char *path;
};
typedef struct _virDomainOSACPITableDef virDomainOSACPITableDef;
void virDomainOSACPITableDefFree(virDomainOSACPITableDef *def);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainOSACPITableDef, virDomainOSACPITableDefFree);
struct _virDomainOSDef {
int type;
virDomainOsDefFirmware firmware;
@ -2503,7 +2521,8 @@ struct _virDomainOSDef {
char *cmdline;
char *dtb;
char *root;
char *slic_table;
size_t nacpiTables;
virDomainOSACPITableDef **acpiTables;
virDomainLoaderDef *loader;
char *bootloader;
char *bootloaderArgs;

View File

@ -611,6 +611,8 @@ virDomainObjTaint;
virDomainObjUpdateModificationImpact;
virDomainObjWait;
virDomainObjWaitUntil;
virDomainOsACPITableTypeFromString;
virDomainOsACPITableTypeToString;
virDomainOsDefFirmwareTypeFromString;
virDomainOsDefFirmwareTypeToString;
virDomainOSTypeFromString;

View File

@ -582,8 +582,9 @@ libxlMakeDomBuildInfo(virDomainDef *def,
VIR_TRISTATE_SWITCH_ON);
#endif
/* copy SLIC table path to acpi_firmware */
b_info->u.hvm.acpi_firmware = g_strdup(def->os.slic_table);
/* copy the table path to acpi_firmware */
if (def->os.nacpiTables)
b_info->u.hvm.acpi_firmware = g_strdup(def->os.acpiTables[0]->path);
if (def->nsounds > 0) {
/*

View File

@ -106,6 +106,7 @@ xenParseXLOS(virConf *conf, virDomainDef *def, virCaps *caps)
g_autofree char *bios = NULL;
g_autofree char *bios_path = NULL;
g_autofree char *boot = NULL;
g_autofree char *slic = NULL;
int val = 0;
if (xenConfigGetString(conf, "bios", &bios, NULL) < 0)
@ -133,8 +134,15 @@ xenParseXLOS(virConf *conf, virDomainDef *def, virCaps *caps)
}
}
if (xenConfigCopyStringOpt(conf, "acpi_firmware", &def->os.slic_table) < 0)
if (xenConfigCopyStringOpt(conf, "acpi_firmware", &slic) < 0)
return -1;
if (slic != NULL) {
def->os.nacpiTables = 1;
def->os.acpiTables = g_new0(virDomainOSACPITableDef *, 1);
def->os.acpiTables[0] = g_new0(virDomainOSACPITableDef, 1);
def->os.acpiTables[0]->type = VIR_DOMAIN_OS_ACPI_TABLE_TYPE_SLIC;
def->os.acpiTables[0]->path = g_steal_pointer(&slic);
}
if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
return -1;
@ -1130,8 +1138,9 @@ xenFormatXLOS(virConf *conf, virDomainDef *def)
return -1;
}
if (def->os.slic_table &&
xenConfigSetString(conf, "acpi_firmware", def->os.slic_table) < 0)
if (def->os.nacpiTables &&
xenConfigSetString(conf, "acpi_firmware",
def->os.acpiTables[0]->path) < 0)
return -1;
if (def->os.kernel &&

View File

@ -127,6 +127,11 @@ VIR_ENUM_IMPL(qemuNumaPolicy,
"restrictive",
);
VIR_ENUM_DECL(qemuACPITableSIG);
VIR_ENUM_IMPL(qemuACPITableSIG,
VIR_DOMAIN_OS_ACPI_TABLE_TYPE_LAST,
"SLIC");
const char *
qemuAudioDriverTypeToString(virDomainAudioType type)
@ -5995,6 +6000,7 @@ qemuBuildBootCommandLine(virCommand *cmd,
{
g_auto(virBuffer) boot_buf = VIR_BUFFER_INITIALIZER;
g_autofree char *boot_opts_str = NULL;
size_t i;
if (def->os.bootmenu) {
if (def->os.bootmenu == VIR_TRISTATE_BOOL_YES)
@ -6028,11 +6034,12 @@ qemuBuildBootCommandLine(virCommand *cmd,
virCommandAddArgList(cmd, "-append", def->os.cmdline, NULL);
if (def->os.dtb)
virCommandAddArgList(cmd, "-dtb", def->os.dtb, NULL);
if (def->os.slic_table) {
for (i = 0; i < def->os.nacpiTables; i++) {
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
virCommandAddArg(cmd, "-acpitable");
virBufferAddLit(&buf, "sig=SLIC,file=");
virQEMUBuildBufferEscapeComma(&buf, def->os.slic_table);
virBufferAsprintf(&buf, "sig=%s,file=",
qemuACPITableSIGTypeToString(def->os.acpiTables[i]->type));
virQEMUBuildBufferEscapeComma(&buf, def->os.acpiTables[i]->path);
virCommandAddArgBuffer(cmd, &buf);
}

View File

@ -2050,9 +2050,10 @@ virSecurityDACRestoreAllLabel(virSecurityManager *mgr,
virSecurityDACRestoreFileLabel(mgr, def->os.dtb) < 0)
rc = -1;
if (def->os.slic_table &&
virSecurityDACRestoreFileLabel(mgr, def->os.slic_table) < 0)
rc = -1;
for (i = 0; i < def->os.nacpiTables; i++) {
if (virSecurityDACRestoreFileLabel(mgr, def->os.acpiTables[i]->path) < 0)
rc = -1;
}
if (def->pstore &&
virSecurityDACRestoreFileLabel(mgr, def->pstore->path) < 0)
@ -2300,11 +2301,12 @@ virSecurityDACSetAllLabel(virSecurityManager *mgr,
user, group, true) < 0)
return -1;
if (def->os.slic_table &&
virSecurityDACSetOwnership(mgr, NULL,
def->os.slic_table,
user, group, true) < 0)
return -1;
for (i = 0; i < def->os.nacpiTables; i++) {
if (virSecurityDACSetOwnership(mgr, NULL,
def->os.acpiTables[i]->path,
user, group, true) < 0)
return -1;
}
if (def->pstore &&
virSecurityDACSetOwnership(mgr, NULL,

View File

@ -3013,9 +3013,10 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManager *mgr,
virSecuritySELinuxRestoreFileLabel(mgr, def->os.dtb, true) < 0)
rc = -1;
if (def->os.slic_table &&
virSecuritySELinuxRestoreFileLabel(mgr, def->os.slic_table, true) < 0)
rc = -1;
for (i = 0; i < def->os.nacpiTables; i++) {
if (virSecuritySELinuxRestoreFileLabel(mgr, def->os.acpiTables[i]->path, true) < 0)
rc = -1;
}
if (def->pstore &&
virSecuritySELinuxRestoreFileLabel(mgr, def->pstore->path, true) < 0)
@ -3443,10 +3444,11 @@ virSecuritySELinuxSetAllLabel(virSecurityManager *mgr,
data->content_context, true) < 0)
return -1;
if (def->os.slic_table &&
virSecuritySELinuxSetFilecon(mgr, def->os.slic_table,
data->content_context, true) < 0)
return -1;
for (i = 0; i < def->os.nacpiTables; i++) {
if (virSecuritySELinuxSetFilecon(mgr, def->os.acpiTables[i]->path,
data->content_context, true) < 0)
return -1;
}
if (def->pstore &&
virSecuritySELinuxSetFilecon(mgr, def->pstore->path,

View File

@ -974,9 +974,10 @@ get_files(vahControl * ctl)
if (vah_add_file(&buf, ctl->def->os.dtb, "r") != 0)
goto cleanup;
if (ctl->def->os.slic_table)
if (vah_add_file(&buf, ctl->def->os.slic_table, "r") != 0)
for (i = 0; i < ctl->def->os.nacpiTables; i++) {
if (vah_add_file(&buf, ctl->def->os.acpiTables[i]->path, "r") != 0)
goto cleanup;
}
if (ctl->def->pstore)
if (vah_add_file(&buf, ctl->def->pstore->path, "rw") != 0)