From b017a43a6d31d2babd6170b6adf7712506f776c2 Mon Sep 17 00:00:00 2001 From: Sridhar Siricilla Date: Wed, 23 Mar 2022 00:19:01 +0530 Subject: soc/intel/common: Add APIs to check CSE's write protection info The patch add APIs to check CSE Region's write protection information. Also, adds helper functions to get the SPI controller's MMIO address to access to BIOS_GPR0 register. The BIOS_GPR0 indicates write and read protection details. During the coreboot image build, write protection is enabled for CSE RO. It is enabled through a Intel MFIT XML configuration. TEST=Verify write protection information of CSE Region Signed-off-by: Sridhar Siricilla Change-Id: If1da0fc410a15996f2e139809f7652127ef8761b Reviewed-on: https://review.coreboot.org/c/coreboot/+/62986 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak --- .../intel/common/block/include/intelblocks/spi.h | 11 +++ src/soc/intel/common/block/spi/spi.c | 81 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) (limited to 'src/soc/intel/common') diff --git a/src/soc/intel/common/block/include/intelblocks/spi.h b/src/soc/intel/common/block/include/intelblocks/spi.h index 38c9a57eb5..4ab4105787 100644 --- a/src/soc/intel/common/block/include/intelblocks/spi.h +++ b/src/soc/intel/common/block/include/intelblocks/spi.h @@ -3,6 +3,17 @@ #ifndef SOC_INTEL_COMMON_BLOCK_SPI_H #define SOC_INTEL_COMMON_BLOCK_SPI_H +#include + +/* + * Check if write protection for CSE RO is enabled or not. + * Returns true if write protection for CSE RO is enabled, false otherwise. + */ +bool is_spi_wp_cse_ro_en(void); + +/* Gets CSE RO's write protected area's base address and limit */ +void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *limit); + /* * SoC overrides * diff --git a/src/soc/intel/common/block/spi/spi.c b/src/soc/intel/common/block/spi/spi.c index 50e1beaf1e..0716e1ae90 100644 --- a/src/soc/intel/common/block/spi/spi.c +++ b/src/soc/intel/common/block/spi/spi.c @@ -1,8 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#define __SIMPLE_DEVICE__ + #include +#include #include #include +#include #include #include #include @@ -20,6 +24,83 @@ const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = { const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map); +#define MMIO_BIOS_GPR0 0x98 + +union spi_bios_gpr0 { + struct { + /* Specified write protection is enabled */ + /* + * This field corresponds to flash address bits 26:12 + * and specifies the lower limit of protected range. + */ + uint32_t protect_range_base:15; + + /* Specifies read protection is enabled */ + uint32_t read_protect_en:1; + + /* + * This field corresponds to flash address bits 26:12 + * and specifies the upper limit of the protected range + */ + uint32_t protect_range_limit:15; + + uint32_t write_protect_en:1; + } __packed fields; + + uint32_t data; +}; + +/* Read SPI BAR 0 from PCI configuration space */ +static uintptr_t get_spi_bar(pci_devfn_t dev) +{ + uintptr_t bar; + + bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + assert(bar != 0); + /* + * Bits 31-12 are the base address as per EDS for SPI, + * Don't care about 0-11 bit + */ + return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK; +} + +static uint32_t spi_read_bar(pci_devfn_t dev, uint32_t offset) +{ + return read32p(get_spi_bar(dev) + offset); +} + +static uint32_t spi_read_bios_gpr0(void) +{ + return spi_read_bar(PCH_DEV_SPI, MMIO_BIOS_GPR0); +} + +static uint32_t spi_get_wp_cse_ro_start_offset(union spi_bios_gpr0 bios_gpr0) +{ + return bios_gpr0.fields.protect_range_base << 12; +} + +static uint32_t spi_get_wp_cse_ro_limit(union spi_bios_gpr0 bios_gpr0) +{ + return bios_gpr0.fields.protect_range_limit << 12 | 0xfff; +} + +bool is_spi_wp_cse_ro_en(void) +{ + union spi_bios_gpr0 bios_gpr0; + + bios_gpr0.data = spi_read_bios_gpr0(); + return !!bios_gpr0.fields.write_protect_en; +} + +void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *limit) +{ + union spi_bios_gpr0 bios_gpr0; + + bios_gpr0.data = spi_read_bios_gpr0(); + *base = spi_get_wp_cse_ro_start_offset(bios_gpr0); + *limit = spi_get_wp_cse_ro_limit(bios_gpr0); +} + static int spi_dev_to_bus(struct device *dev) { return spi_soc_devfn_to_bus(dev->path.pci.devfn); -- cgit v1.2.3