@@ -556,6 +556,13 @@ static __init int match_config_table(const efi_guid_t *guid,
for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
if (!efi_guidcmp(*guid, table_types[i].guid)) {
+ if (IS_ENABLED(CONFIG_XEN_EFI) &&
+ !xen_efi_config_table_is_usable(guid, table)) {
+ if (table_types[i].name[0])
+ pr_cont("(%s=0x%lx) ",
+ table_types[i].name, table);
+ return 1;
+ }
*(table_types[i].ptr) = table;
if (table_types[i].name[0])
pr_cont("%s=0x%lx ",
@@ -292,3 +292,72 @@ void __init xen_efi_runtime_setup(void)
efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
efi.reset_system = xen_efi_reset_system;
}
+
+static const efi_guid_t cfg_table_allow_list[] __initconst = {
+ ACPI_20_TABLE_GUID,
+ ACPI_TABLE_GUID,
+ SMBIOS_TABLE_GUID,
+ SMBIOS3_TABLE_GUID,
+};
+
+bool __init xen_efi_config_table_is_usable(const efi_guid_t *guid,
+ unsigned long table)
+{
+ u32 memtype;
+ int i, rc;
+
+ if (!efi_enabled(EFI_PARAVIRT))
+ return true;
+
+ for (i = 0; i < ARRAY_SIZE(cfg_table_allow_list); i++) {
+ if (!efi_guidcmp(*guid, cfg_table_allow_list[i]))
+ return true;
+ }
+
+ if (efi_enabled(EFI_MEMMAP)) {
+ /* check against the EFI memory map */
+ efi_memory_desc_t md;
+
+ rc = efi_mem_desc_lookup(table, &md);
+ if (rc) {
+ pr_warn("Failed to lookup header 0x%lx in EFI memory map (%d)\n",
+ table, rc);
+ return false;
+ }
+ memtype = md.type;
+ } else {
+ /* check against the Xen hypercall */
+ struct xen_platform_op op = {
+ .cmd = XENPF_firmware_info,
+ .u.firmware_info = {
+ .type = XEN_FW_EFI_INFO,
+ .index = XEN_FW_EFI_MEM_INFO,
+ .u.efi_info.mem.addr = table,
+ .u.efi_info.mem.size = U64_MAX - table,
+ }
+ };
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ rc = HYPERVISOR_platform_op(&op);
+ if (rc) {
+ pr_warn("Failed to lookup header 0x%lx in Xen memory map (%d)\n",
+ table, rc);
+ return false;
+ }
+ memtype = info->mem.type;
+ }
+
+ switch (memtype) {
+ case EFI_RUNTIME_SERVICES_CODE:
+ case EFI_RUNTIME_SERVICES_DATA:
+ case EFI_ACPI_RECLAIM_MEMORY:
+ case EFI_RESERVED_TYPE:
+ return true;
+ case EFI_BOOT_SERVICES_DATA:
+ break;
+ default:
+ return false;
+ }
+
+ return false;
+}
@@ -1351,4 +1351,6 @@ struct linux_efi_initrd {
/* Header of a populated EFI secret area */
#define EFI_SECRET_TABLE_HEADER_GUID EFI_GUID(0x1e74f542, 0x71dd, 0x4d66, 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b)
+bool xen_efi_config_table_is_usable(const efi_guid_t *, unsigned long table);
+
#endif /* _LINUX_EFI_H */