Sridhar Siricilla has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/62986 )
Change subject: soc/intel/common: Add APIs to check CSE's write protection info ......................................................................
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 GPRD register which is part of Descriptor Region.
TEST=Verify write protection information of CSE Region
Signed-off-by: Sridhar Siricilla sridhar.siricilla@intel.com Change-Id: If1da0fc410a15996f2e139809f7652127ef8761b --- M src/soc/intel/common/block/include/intelblocks/spi.h M src/soc/intel/common/block/spi/spi.c 2 files changed, 94 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/86/62986/1
diff --git a/src/soc/intel/common/block/include/intelblocks/spi.h b/src/soc/intel/common/block/include/intelblocks/spi.h index 38c9a57..7997734 100644 --- a/src/soc/intel/common/block/include/intelblocks/spi.h +++ b/src/soc/intel/common/block/include/intelblocks/spi.h @@ -4,6 +4,15 @@ #define SOC_INTEL_COMMON_BLOCK_SPI_H
/* + * Check if write protection for CSE RO is enabled or not. + * Returns 1 if write protection for CSE RO is enabled, 0 otherwise. + */ +bool is_spi_wp_cse_ro_en(void); + +/* Gets CSE's write protected area's base address and size */ +void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *size); + +/* * SoC overrides * * All new SoC must implement below functionality. diff --git a/src/soc/intel/common/block/spi/spi.c b/src/soc/intel/common/block/spi/spi.c index 50e1bea..a753a3f 100644 --- a/src/soc/intel/common/block/spi/spi.c +++ b/src/soc/intel/common/block/spi/spi.c @@ -1,14 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */
+#define __SIMPLE_DEVICE__ + #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> +#include <device/pci_ops.h> #include <device/spi.h> #include <intelblocks/fast_spi.h> #include <intelblocks/gspi.h> #include <intelblocks/spi.h> #include <soc/pci_devs.h> #include <spi-generic.h> +#include <device/mmio.h>
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = { { .ctrlr = &fast_spi_flash_ctrlr, .bus_start = 0, .bus_end = 0 }, @@ -20,6 +24,87 @@
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; +}; + +#if ENV_RAMSTAGE + +/* 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); +} +#endif + static int spi_dev_to_bus(struct device *dev) { return spi_soc_devfn_to_bus(dev->path.pci.devfn);