Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/26888
Change subject: [WIP]sb/intel/common/spi: Add method to probe protected regions ......................................................................
[WIP]sb/intel/common/spi: Add method to probe protected regions
In preparation for VBOOT introduce a method to check if a region is write-protected. For example the RO region.
Change-Id: I40812eacba552d9c24790942fc5612b4836238f3 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/include/spi-generic.h M src/southbridge/intel/common/spi.c 2 files changed, 82 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/88/26888/1
diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h index e3e7f82..bfbf03d 100644 --- a/src/include/spi-generic.h +++ b/src/include/spi-generic.h @@ -145,6 +145,8 @@ struct spi_flash *flash); int (*flash_protect)(const struct spi_flash *flash, const struct region *region); + bool (*get_write_protection)(const struct spi_flash *flash, + const struct region *region); };
/*----------------------------------------------------------------------- diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index bd89025..c87a85c 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -28,7 +28,7 @@ #include <device/pci_ids.h> #include <device/pci.h> #include <spi_flash.h> - +#include <memrange.h> #include <spi-generic.h>
#define HSFC_FCYCLE_OFF 1 /* 1-2: FLASH Cycle */ @@ -1006,6 +1006,80 @@ return ret; }
+static u32 spi_fpr_limit(const u32 reg) +{ + u32 mask, limit_shift; + if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX)) { + mask = ICH7_SPI_FPR_MASK; + limit_shift = ICH7_SPI_FPR_LIMIT_SHIFT; + } else { + mask = ICH9_SPI_FPR_MASK; + limit_shift = ICH9_SPI_FPR_LIMIT_SHIFT; + } + + return ((reg >> limit_shift) & mask) << SPI_FPR_SHIFT; +} + +static u32 spi_fpr_base(const u32 reg) +{ + u32 mask; + if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX)) { + mask = ICH7_SPI_FPR_MASK; + } else { + mask = ICH9_SPI_FPR_MASK; + } + + return ((reg >> SPI_FPR_BASE_SHIFT) & mask) << SPI_FPR_SHIFT; +} + + +/* + * Test if a region defined by [start, start+size-1] is write-protected using + * Flash Protected Range (FPR) register if available. + * Returns true if the whole region is write-protected by one ore multiple + * protected range regions. + */ +static bool spi_get_write_protection(const struct spi_flash *flash, + const struct region *region) +{ + const ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr); + const u32 start = region_offset(region); + const u32 end = start + region_sz(region) - 1; + int fpr; + uint32_t *fpr_base = cntlr->fpr; + struct memranges prot_space; + struct range_entry *entry; + bool ret = false; + + memranges_init_empty(&prot_space, NULL, 0); + + /* Merge active protected regions */ + for (fpr = 0; (fpr < cntlr->fpr_max) && read32(&fpr_base[fpr]); fpr++) { + u32 reg = read32(&fpr_base[fpr]); + if (!(reg & SPI_FPR_WPE)) + continue; + + memranges_insert(&prot_space, spi_fpr_base(reg), + spi_fpr_limit(reg) + 1 - spi_fpr_base(reg), 0); + } + + for (entry = prot_space.entries; entry; + entry = memranges_next_entry(&prot_space, entry)) { + if (range_entry_base(entry) <= start && + range_entry_end(entry) >= end) + { + ret = true; + break; + } + } + + memranges_teardown(&prot_space); + + printk(BIOS_INFO, "%s: Range 0x%08x-0x%08x is %swrite-protected\n", + __func__, start, end, ret ? " " : "not "); + return ret; +} + /* * Protect range of SPI flash defined by [start, start+size-1] using Flash * Protected Range (FPR) register if available. @@ -1021,6 +1095,10 @@ int fpr; uint32_t *fpr_base;
+ /* Test if region is already covered by FPR */ + if (spi_get_write_protection(flash, region)) + return 0; + fpr_base = cntlr->fpr;
/* Find first empty FPR */ @@ -1056,6 +1134,7 @@ .max_xfer_size = member_size(ich9_spi_regs, fdata), .flash_probe = spi_flash_programmer_probe, .flash_protect = spi_flash_protect, + .get_write_protection = spi_get_write_protection, };
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {