From 4a74a5ffd78f29493824a597ff13e2c05513a1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Tue, 4 Oct 2022 11:44:27 +0200 Subject: [PATCH] mb/protectli/vault_cml: Disable PTT and SPI TPM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform supports a discrete LPC TPM module. However, ME firmware enables PTT by default and descriptor is configured for SPI TPM on the platform's original firmware. So disabling PTT in ME is not enough, because it falls back to SPI TPM. Ensure PTT is disabled in ME and SPI TPM is disabled in descriptor soft straps. TEST=Boot VP4650 and see LPC TPM is recognized by coreboot. Signed-off-by: Michał Żygowski Change-Id: I3764e085f2eb5ae957b9087d150320def7af4fc6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/68920 Tested-by: build bot (Jenkins) Reviewed-by: Krystian Hebel --- src/mainboard/protectli/vault_cml/mainboard.c | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/mainboard/protectli/vault_cml/mainboard.c b/src/mainboard/protectli/vault_cml/mainboard.c index 24f46c9013..1e06fc5fee 100644 --- a/src/mainboard/protectli/vault_cml/mainboard.c +++ b/src/mainboard/protectli/vault_cml/mainboard.c @@ -1,12 +1,30 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include #include #include +#include +#include #include +#include +#include +#include #include #include +static bool need_global_reset = false; + +/* Flash Master 1 : HOST/BIOS */ +#define FLMSTR1 0x80 + +#define FLASH_SIGNATURE_OFFSET 0x10 +#define FLMSTR_WR_SHIFT_V2 20 +#define FLASH_SIGNATURE_VAL 0x0FF0A55A + +#define SI_DESC_SIZE (4 * KiB) +#define SI_DESC_REGION "SI_DESC" + const char *smbios_mainboard_product_name(void) { char processor_name[49]; @@ -29,6 +47,81 @@ static void mainboard_final(void *unused) beep(1500, 100); } +/* It checks whether host (Flash Master 1) has write access to the Descriptor Region or not */ +static bool is_descriptor_writeable(uint8_t *desc) +{ + /* Check flash has valid signature */ + if (read32((void *)(desc + FLASH_SIGNATURE_OFFSET)) != FLASH_SIGNATURE_VAL) { + printk(BIOS_ERR, "Flash Descriptor is not valid\n"); + printk(BIOS_ERR, "Descriptor needs to be fixed to ensure proper operation\n"); + return false; + } + + /* Check host has write access to the Descriptor Region */ + if (!((read32((void *)(desc + FLMSTR1)) >> FLMSTR_WR_SHIFT_V2) & BIT(0))) { + printk(BIOS_ERR, "Host doesn't have write access to Descriptor Region\n"); + return false; + } + + return true; +} + +static void configure_descriptor_for_lpc_tpm(void) +{ + uint8_t si_desc_buf[SI_DESC_SIZE]; + struct region_device desc_rdev; + + if (fmap_locate_area_as_rdev_rw(SI_DESC_REGION, &desc_rdev) < 0) { + printk(BIOS_ERR, "Failed to locate %s in the FMAP\n", SI_DESC_REGION); + return; + } + + if (rdev_readat(&desc_rdev, si_desc_buf, 0, SI_DESC_SIZE) != SI_DESC_SIZE) { + printk(BIOS_ERR, "Failed to read Descriptor Region from SPI Flash\n"); + return; + } + + if (!is_descriptor_writeable(si_desc_buf)) + return; + + /* Disable SPI TPM if necessary */ + if ((si_desc_buf[0x1f0] & 0xfe) == si_desc_buf[0x1f0]) { + printk(BIOS_DEBUG, "Update of Descriptor is not required!\n"); + return; + } + + si_desc_buf[0x1f0] &= 0xfe; + + if (rdev_eraseat(&desc_rdev, 0, SI_DESC_SIZE) != SI_DESC_SIZE) { + printk(BIOS_ERR, "Failed to erase Descriptor Region area\n"); + return; + } + + if (rdev_writeat(&desc_rdev, si_desc_buf, 0, SI_DESC_SIZE) != SI_DESC_SIZE) { + printk(BIOS_ERR, "Failed to update Descriptor Region\n"); + return; + } + + printk(BIOS_DEBUG, "Update of Descriptor successful\n"); + need_global_reset = true; +} + +void mainboard_silicon_init_params(FSPS_UPD *supd) +{ + /* Call it right before Silicon Init, so that we avoid EOP */ + configure_descriptor_for_lpc_tpm(); + cse_enable_ptt(false); + /* + * We wait with global reset after descriptor update until PTT state change to avoid + * double global reset. In case PTT was already disabled or cse_enable_ptt will fail + * for some reason, but descriptor has been updated we need to do global reset here, + * otherwise cse_enable_ptt will do the global reset and the branch below won't be + * reached. + */ + if (need_global_reset) + do_global_reset(); +} + struct chip_operations mainboard_ops = { .final = mainboard_final, };