sec/intel/txt: Bail if var MTRRs cannot snugly cache the BIOS ACM
When caching the BIOS ACM, one must cache less than a page (4 KiB) of
unused memory past the end of the BIOS ACM. Failure to do so on Haswell
will result in a lovely TXT reset with Class Code 5, Major Error Code 2.
The current approach uses a single variable MTRR to cache the whole BIOS
ACM. Before fighting with the variable MTRRs in assembly code, ensure
that enough variable MTRRs exist to cache the BIOS ACM's size. Since the
code checks that the ACM base is aligned to its size, each `one` bit in
the ACM size will require one variable MTRR to properly cache the ACM.
One of the several BIOS ACMs for Haswell has a size of 101504 bytes.
This is 0x18c80 in hexadecimal, and 0001 1000 1100 1000 0000 in binary.
After aligning up the BIOS ACM size to a page boundary, the resulting
size is 0x19000 in hexadecimal, and 0001 1001 0000 0000 0000 in binary.
To successfully invoke said ACM, its base must be a multiple of 0x20000
and three variable MTRRs must be used to cache the ACM. The MTRR ranges
must be contiguous and cover 0x10000, 0x8000, 0x1000 bytes, in order.
The assembly code is updated in a follow-up, and relies on these checks.
Change-Id: I480dc3e4a9e4a59fbb73d571fd62b0257abc65b3
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/46422
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/security/intel/txt/common.c b/src/security/intel/txt/common.c
index e73defb..5f8a976 100644
--- a/src/security/intel/txt/common.c
+++ b/src/security/intel/txt/common.c
@@ -6,6 +6,7 @@
#include <cpu/x86/cr.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
+#include <cpu/x86/mtrr.h>
#include <lib.h>
#include <smp/node.h>
#include <string.h>
@@ -266,6 +267,17 @@
return -1;
}
+ /*
+ * When setting up the MTRRs to cache the BIOS ACM, one must cache less than
+ * a page (4 KiB) of unused memory after the BIOS ACM. On Haswell, failure
+ * to do so will cause a TXT reset with Class Code 5, Major Error Code 2.
+ */
+ if (popcnt(ALIGN_UP(acm_len, 4096)) > get_var_mtrr_count()) {
+ printk(BIOS_ERR, "TEE-TXT: Not enough MTRRs to cache this BIOS ACM's size.\n");
+ rdev_munmap(&acm, acm_data);
+ return -1;
+ }
+
if (CONFIG(INTEL_TXT_LOGGING))
txt_dump_acm_info(acm_data);