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, };