From ffbb4b2b11f2bb875fbaca0137615b592ba0cd9c Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 15 Oct 2020 23:25:58 +0200 Subject: intel/txt: Add `txt_get_chipset_dpr` function Due to platform-specific constraints, it is not possible to enable DPR by programming the MCH's DPR register in ramstage. Instead, assume it has been programmed earlier and check that its value is valid. If it is, then simply configure DPR in TXT public base with the same parameters. Note that some bits only exist on MCH DPR, and thus need to be cleared. Implement this function on most client platforms. For Skylake and newer, place it in common System Agent code. Also implement it for Haswell, for which the rest of Intel TXT support will be added in subsequent commits. Do not error out if DPR is larger than expected. On some platforms, such as Haswell, MRC decides the size of DPR, and cannot be changed easily. Reimplementing MRC is easier than working around its limitations anyway. Change-Id: I391383fb03bd6636063964ff249c75028e0644cf Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/46490 Reviewed-by: Arthur Heymans Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/northbridge/intel/haswell/memmap.c | 10 ++++-- src/security/intel/txt/ramstage.c | 41 ++++++++++++++++++---- src/security/intel/txt/txt_platform.h | 12 +++++++ .../common/block/systemagent/systemagent_early.c | 7 ++++ 4 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/security/intel/txt/txt_platform.h diff --git a/src/northbridge/intel/haswell/memmap.c b/src/northbridge/intel/haswell/memmap.c index ac36e25999..02d120b119 100644 --- a/src/northbridge/intel/haswell/memmap.c +++ b/src/northbridge/intel/haswell/memmap.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "haswell.h" @@ -23,6 +24,11 @@ static size_t northbridge_get_tseg_size(void) return CONFIG_SMM_TSEG_SIZE; } +union dpr_register txt_get_chipset_dpr(void) +{ + return (union dpr_register) { .raw = pci_read_config32(HOST_BRIDGE, DPR) }; +} + /* * Return the topmost memory address below 4 GiB available for general * use, from software's view of memory. Do not confuse this with TOLUD, @@ -39,9 +45,7 @@ static uintptr_t top_of_low_usable_memory(void) */ uintptr_t tolum = northbridge_get_tseg_base(); - const union dpr_register dpr = { - .raw = pci_read_config32(HOST_BRIDGE, DPR), - }; + const union dpr_register dpr = txt_get_chipset_dpr(); /* Subtract DMA Protected Range size if enabled */ if (dpr.epm) diff --git a/src/security/intel/txt/ramstage.c b/src/security/intel/txt/ramstage.c index 263bc9daa6..f532a2fbd8 100644 --- a/src/security/intel/txt/ramstage.c +++ b/src/security/intel/txt/ramstage.c @@ -13,6 +13,7 @@ #include #include "txt.h" +#include "txt_platform.h" #include "txt_register.h" #include "txt_getsec.h" @@ -233,16 +234,42 @@ static void lockdown_intel_txt(void *unused) printk(BIOS_INFO, "TEE-TXT: DPR capable %x\n", dpr_capable); if (dpr_capable) { - /* Protect 3 MiB below TSEG and lock register */ - union dpr_register dpr = { - .lock = 1, - .size = 3, - .top = tseg_base / MiB, - }; - write64((void *)TXT_DPR, dpr.raw); + /* Verify the DPR settings on the MCH and mirror them to TXT public space */ + union dpr_register dpr = txt_get_chipset_dpr(); + + printk(BIOS_DEBUG, "TEE-TXT: MCH DPR 0x%08x\n", dpr.raw); + + printk(BIOS_DEBUG, "TEE-TXT: MCH DPR base @ 0x%08x size %u MiB\n", + (dpr.top - dpr.size) * MiB, dpr.size); // DPR TODO: implement SA_ENABLE_DPR in the intelblocks + if (!dpr.lock) { + printk(BIOS_ERR, "TEE-TXT: MCH DPR not locked.\n"); + return; + } + + if (!dpr.epm || !dpr.prs) { + printk(BIOS_ERR, "TEE-TXT: MCH DPR protection not active.\n"); + return; + } + + if (dpr.size < 3) { + printk(BIOS_ERR, "TEE-TXT: MCH DPR configured size is too small.\n"); + return; + } + + if (dpr.top * MiB != tseg_base) { + printk(BIOS_ERR, "TEE-TXT: MCH DPR top does not equal TSEG base.\n"); + return; + } + + /* Clear reserved bits */ + dpr.prs = 0; + dpr.epm = 0; + + write64((void *)TXT_DPR, dpr.raw); + printk(BIOS_INFO, "TEE-TXT: TXT.DPR 0x%08x\n", read32((void *)TXT_DPR)); } diff --git a/src/security/intel/txt/txt_platform.h b/src/security/intel/txt/txt_platform.h new file mode 100644 index 0000000000..8881cab331 --- /dev/null +++ b/src/security/intel/txt/txt_platform.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SECURITY_INTEL_TXT_PLATFORM_H__ +#define __SECURITY_INTEL_TXT_PLATFORM_H__ + +#include +#include "txt_register.h" + +/* Prototypes to be defined in chipset code */ +union dpr_register txt_get_chipset_dpr(void); + +#endif /* __SECURITY_INTEL_TXT_PLATFORM_H__ */ diff --git a/src/soc/intel/common/block/systemagent/systemagent_early.c b/src/soc/intel/common/block/systemagent/systemagent_early.c index ffb6404aa2..53d6077e5f 100644 --- a/src/soc/intel/common/block/systemagent/systemagent_early.c +++ b/src/soc/intel/common/block/systemagent/systemagent_early.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -145,3 +147,8 @@ size_t sa_get_tseg_size(void) { return sa_get_gsm_base() - sa_get_tseg_base(); } + +union dpr_register txt_get_chipset_dpr(void) +{ + return (union dpr_register) { .raw = pci_read_config32(SA_DEV_ROOT, DPR) }; +} -- cgit v1.2.3