summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/x86/Kconfig13
-rw-r--r--src/cpu/x86/smm/Makefile.inc3
-rw-r--r--src/cpu/x86/smm/pci_resource_store.c73
-rw-r--r--src/cpu/x86/smm/smm_module_handler.c7
-rw-r--r--src/cpu/x86/smm/smm_module_loader.c3
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)