diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/x86/Kconfig | 13 | ||||
-rw-r--r-- | src/cpu/x86/smm/Makefile.inc | 3 | ||||
-rw-r--r-- | src/cpu/x86/smm/pci_resource_store.c | 73 | ||||
-rw-r--r-- | src/cpu/x86/smm/smm_module_handler.c | 7 | ||||
-rw-r--r-- | src/cpu/x86/smm/smm_module_loader.c | 3 |
5 files changed, 99 insertions, 0 deletions
diff --git a/src/cpu/x86/Kconfig b/src/cpu/x86/Kconfig index edba27bd40..d95e6cc4c3 100644 --- a/src/cpu/x86/Kconfig +++ b/src/cpu/x86/Kconfig @@ -168,6 +168,19 @@ config SMM_LAPIC_REMAP_MITIGATION || NORTHBRIDGE_INTEL_E7505 || NORTHBRIDGE_INTEL_IRONLAKE default n +config SMM_PCI_RESOURCE_STORE + bool + default n + help + This option enables support for storing PCI resources in SMRAM so + SMM can tell if they've been altered. + +config SMM_PCI_RESOURCE_STORE_NUM_SLOTS + int + default 8 + help + Number of slots available to store PCI BARs in SMRAM + config X86_AMD_FIXED_MTRRS bool default n diff --git a/src/cpu/x86/smm/Makefile.inc b/src/cpu/x86/smm/Makefile.inc index 327b6c6720..dbe9c75262 100644 --- a/src/cpu/x86/smm/Makefile.inc +++ b/src/cpu/x86/smm/Makefile.inc @@ -1,6 +1,9 @@ ## SPDX-License-Identifier: GPL-2.0-only ramstage-y += smm_module_loader.c +ramstage-$(CONFIG_SMM_PCI_RESOURCE_STORE) += pci_resource_store.c + +smm-$(CONFIG_SMM_PCI_RESOURCE_STORE) += pci_resource_store.c ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) $(eval $(call create_class_compiler,smm,x86_32)) diff --git a/src/cpu/x86/smm/pci_resource_store.c b/src/cpu/x86/smm/pci_resource_store.c new file mode 100644 index 0000000000..56bb766cc3 --- /dev/null +++ b/src/cpu/x86/smm/pci_resource_store.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cpu/x86/smm.h> +#include <device/device.h> +#include <device/pci_def.h> +#include <device/pci_ops.h> + +void smm_pci_get_stored_resources(const volatile struct smm_pci_resource_info **out_slots, + size_t *out_size) +{ + *out_slots = smm_get_pci_resource_store(); + *out_size = CONFIG_SMM_PCI_RESOURCE_STORE_NUM_SLOTS; +} + +bool smm_pci_resource_store_fill_resources(struct smm_pci_resource_info *slots, size_t num_slots, + const struct device **devices, size_t num_devices) +{ + size_t i_slot = 0; + + for (size_t i_dev = 0; i_dev < num_devices; i_dev++) { + if (i_slot >= num_slots) { + printk(BIOS_ERR, "Failed to store all PCI resources, number of devices exceeds %zd slots\n", + num_slots); + return false; + } + + if (!is_pci(devices[i_dev])) { + printk(BIOS_WARNING, "Skipping storing PCI resources for device at index %zd, not a PCI device\n", + i_dev); + continue; + } + + pci_devfn_t pci_addr = PCI_BDF(devices[i_dev]); + slots[i_slot].pci_addr = pci_addr; + slots[i_slot].class_device = PCI_CLASS_GET_DEVICE(devices[i_dev]->class); + slots[i_slot].class_prog = PCI_CLASS_GET_PROG(devices[i_dev]->class); + + /* Use the resource list to get our BARs. */ + if (!devices[i_dev]->resource_list) + continue; + + size_t i_res = 0; + for (const struct resource *res = devices[i_dev]->resource_list; res != NULL; + res = res->next) { + slots[i_slot].resources[i_res] = *res; + slots[i_slot].resources[i_res].next = NULL; + + if (i_res > 0) + slots[i_slot].resources[i_res - 1].next = (struct resource *)&slots[i_slot].resources[i_res]; + + if (++i_res >= SMM_PCI_RESOURCE_STORE_NUM_RESOURCES) { + if (res->next) + printk(BIOS_WARNING, "Number of PCI resources exceeds supported storage count\n"); + break; + } + } + + i_slot++; + } + + return true; +} + +void __weak smm_mainboard_pci_resource_store_init(struct smm_pci_resource_info *slots, + size_t size) +{ +} + +void smm_pci_resource_store_init(struct smm_runtime *smm_runtime) +{ + smm_mainboard_pci_resource_store_init(&smm_runtime->pci_resources[0], + CONFIG_SMM_PCI_RESOURCE_STORE_NUM_SLOTS); +} diff --git a/src/cpu/x86/smm/smm_module_handler.c b/src/cpu/x86/smm/smm_module_handler.c index 1b3c93b780..3415b02842 100644 --- a/src/cpu/x86/smm/smm_module_handler.c +++ b/src/cpu/x86/smm/smm_module_handler.c @@ -195,6 +195,13 @@ asmlinkage void smm_handler_start(void *arg) southbridge_smi_set_eos(); } +#if CONFIG(SMM_PCI_RESOURCE_STORE) +const volatile struct smm_pci_resource_info *smm_get_pci_resource_store(void) +{ + return &smm_runtime.pci_resources[0]; +} +#endif + RMODULE_ENTRY(smm_handler_start); /* Provide a default implementation for all weak handlers so that relocation diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c index 1b04e8894d..6452707f75 100644 --- a/src/cpu/x86/smm/smm_module_loader.c +++ b/src/cpu/x86/smm/smm_module_loader.c @@ -343,6 +343,9 @@ static void setup_smihandler_params(struct smm_runtime *mod_params, mod_params->smm_log_level = mainboard_set_smm_log_level(); else mod_params->smm_log_level = 0; + + if (CONFIG(SMM_PCI_RESOURCE_STORE)) + smm_pci_resource_store_init(mod_params); } static void print_region(const char *name, const struct region region) |