Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/46556 )
Change subject: sec/intel/txt: Account for SINIT ACM's of different sizes ......................................................................
sec/intel/txt: Account for SINIT ACM's of different sizes
This checks the size of the ACM at runtime before programming the TXT SINIT BASE/SIZE and HEAP BASE/SIZE.
Change-Id: Ia3e81d051a03b54233eef6ccdc4740c1a709be40 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/security/intel/txt/ramstage.c 1 file changed, 65 insertions(+), 17 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/56/46556/1
diff --git a/src/security/intel/txt/ramstage.c b/src/security/intel/txt/ramstage.c index f532a2f..3105d30 100644 --- a/src/security/intel/txt/ramstage.c +++ b/src/security/intel/txt/ramstage.c @@ -194,6 +194,18 @@ } }
+/* fms: find most significant bit set, stolen from Linux Kernel Source. */ +static inline unsigned int fms(unsigned int x) +{ + unsigned int r; + + __asm__("bsrl %1,%0\n\t" + "jnz 1f\n\t" + "movl $0,%0\n" + "1:" : "=r" (r) : "mr" (x)); + return r; +} + /** * Finalize the TXT device. * @@ -274,22 +286,58 @@ read32((void *)TXT_DPR)); }
- /* - * Document Number: 558294 - * Chapter 5.5.6.3 Intel TXT Heap Memory Region + /* Document Number: 558294 + * Chapter 5.5.5.6 Intel TXT Device Memory + * + * +------------+ TSEG_BASE / DPR.TOP + * | TXT HEAP | + * +------------+ TSEG_BASE - 1 MiB + SINIT ACM SIZE + * | TXT SINIT | + * +------------+ TSEG_BASE - 1 MiB + * | MLE code | + * | Page Table | + * +------------+ TSEG_BASE - at least 3 MiB */ - write64((void *)TXT_HEAP_SIZE, 0xE0000); - write64((void *)TXT_HEAP_BASE, - ALIGN_DOWN(tseg_base - read64((void *)TXT_HEAP_SIZE), 4096)); + + struct cbfsf fh; + uint32_t compression_algo; + size_t decompressed_size; + + void *sinit_base = (void *)(tseg_base - 1 * MiB); + + if (cbfs_boot_locate(&fh, CONFIG_INTEL_TXT_CBFS_SINIT_ACM, NULL)) { + printk(BIOS_ERR, "TEE-TXT: Couldn't locate SINIT ACM in CBFS.\n"); + /* Clear where SINIT and Heap would have been. */ + memset(sinit_base, 0, 1 * MiB); + return; + } + + cbfsf_decompression_info(&fh, &compression_algo, &decompressed_size); + + /* Align the SINIT size to a power of 2 */ + const size_t sinit_size = IS_POWER_OF_2(decompressed_size) ? + decompressed_size : 1 << (fms(decompressed_size) + 1); + + if (sinit_size >= 1 * MiB) { + printk(BIOS_ERR, "TEE-TXT: Invalid SINIT ACM size"); + /* Clear where SINIT and Heap would have been. */ + memset(sinit_base, 0, 1 * MiB); + return; + }
/* * Document Number: 558294 * Chapter 5.5.6.2 SINIT Memory Region */ - write64((void *)TXT_SINIT_SIZE, 0x20000); - write64((void *)TXT_SINIT_BASE, - ALIGN_DOWN(read64((void *)TXT_HEAP_BASE) - - read64((void *)TXT_SINIT_SIZE), 4096)); + write64((void *)TXT_SINIT_SIZE, sinit_size); + write64((void *)TXT_SINIT_BASE, (uint64_t)(uintptr_t)sinit_base); + + /* + * Document Number: 558294 + * Chapter 5.5.6.3 Intel TXT Heap Memory Region + */ + write64((void *)TXT_HEAP_SIZE, 1 * MiB - sinit_size); + write64((void *)TXT_HEAP_BASE, tseg_base - 1 * MiB + sinit_size);
/* * BIOS Data Format @@ -309,12 +357,12 @@ data.bdr.version = 5;
data.bdr.no_logical_procs = dev_count_cpu(); - - void *sinit_base = (void *)(uintptr_t)read64((void *)TXT_SINIT_BASE); - data.bdr.bios_sinit_size = cbfs_boot_load_file(CONFIG_INTEL_TXT_CBFS_SINIT_ACM, - sinit_base, - read64((void *)TXT_SINIT_SIZE), - CBFS_TYPE_RAW); + data.bdr.bios_sinit_size = cbfs_load_and_decompress(&fh.data, + 0, + region_device_sz(&fh.data), + sinit_base, + sinit_size, + compression_algo);
if (data.bdr.bios_sinit_size) { printk(BIOS_INFO, "TEE-TXT: Placing SINIT ACM in memory.\n"); @@ -323,7 +371,7 @@ } else { printk(BIOS_ERR, "TEE-TXT: Couldn't locate SINIT ACM in CBFS.\n"); /* Clear memory */ - memset(sinit_base, 0, read64((void *)TXT_SINIT_SIZE)); + memset(sinit_base, 0, sinit_size); }
struct cbfsf file;