Furquan Shaikh (furquan@google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17115
-gerrit
commit 28cc672200ae3638a1ff1583eeb2e518a66c624c Author: Furquan Shaikh furquan@chromium.org Date: Mon Oct 24 15:23:40 2016 -0700
soc/intel/common: Enable support to write protect SPI flash range
Write-protect SPI flash range provided by caller by using a free Flash Protected Range (FPR) register. This expects SoC to define a callback for providing information about the first FPR register address and maximum number of FPRs supported.
BUG=chrome-os-partner:58896
Change-Id: I4e34ede8784e5587a5e08ffa10e20d2d14e20add Signed-off-by: Furquan Shaikh furquan@chromium.org --- src/soc/intel/common/Kconfig | 4 +++ src/soc/intel/common/Makefile.inc | 1 + src/soc/intel/common/nvm.c | 1 + src/soc/intel/common/spi.c | 66 +++++++++++++++++++++++++++++++++++++++ src/soc/intel/common/spi.h | 45 ++++++++++++++++++++++++++ 5 files changed, 117 insertions(+)
diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig index 8eae23b..affec55 100644 --- a/src/soc/intel/common/Kconfig +++ b/src/soc/intel/common/Kconfig @@ -9,6 +9,10 @@ config CACHE_MRC_SETTINGS bool "Save cached MRC settings" default n
+config SOC_INTEL_COMMON_SPI_PROTECT + bool + default n + if CACHE_MRC_SETTINGS
config MRC_SETTINGS_CACHE_BASE diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc index 13ba21b..888c657 100644 --- a/src/soc/intel/common/Makefile.inc +++ b/src/soc/intel/common/Makefile.inc @@ -19,6 +19,7 @@ postcar-y += util.c ramstage-y += hda_verb.c ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += nvm.c +ramstage-$(CONFIG_SOC_INTEL_COMMON_SPI_PROTECT) += spi.c ramstage-$(CONFIG_SOC_INTEL_COMMON_LPSS_I2C) += lpss_i2c.c ramstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c ramstage-y += util.c diff --git a/src/soc/intel/common/nvm.c b/src/soc/intel/common/nvm.c index 99dcaac..8055657 100644 --- a/src/soc/intel/common/nvm.c +++ b/src/soc/intel/common/nvm.c @@ -23,6 +23,7 @@ #include <soc/spi.h> #include <vendorcode/google/chromeos/chromeos.h> #include "nvm.h" +#include "spi.h"
/* This module assumes the flash is memory mapped just below 4GiB in the * address space for reading. Also this module assumes an area it erased diff --git a/src/soc/intel/common/spi.c b/src/soc/intel/common/spi.c new file mode 100644 index 0000000..8de611a --- /dev/null +++ b/src/soc/intel/common/spi.c @@ -0,0 +1,66 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <console/console.h> +#include "spi.h" + +/* + * Protect range of SPI flash defined by [start, start+size-1] using Flash + * Protected Range(FPR) register if available. + */ +int spi_flash_protect(u32 start, u32 size) +{ + struct fpr_info fpr_info; + u32 end = start + size - 1; + u32 reg; + int fpr; + uintptr_t fpr_base; + + if (spi_get_fpr_info(&fpr_info) == -1) { + printk(BIOS_ERR, "ERROR: FPR Info not found!\n"); + return -1; + } + + fpr_base = fpr_info.base; + + /* Find first empty FPR */ + for (fpr = 0; fpr < fpr_info.max; fpr++) { + reg = read32((void *)fpr_base); + if (reg == 0) + break; + fpr_base += sizeof(uint32_t); + } + + if (fpr >= fpr_info.max) { + printk(BIOS_ERR, "ERROR: No SPI FPR free!\n"); + return -1; + } + + /* Set protected range base and limit */ + reg = SPI_FPR(start, end) | SPI_FPR_WPE; + + /* Set the FPR register and verify it is protected */ + write32((void *)fpr_base, reg); + reg = read32((void *)fpr_base); + if (!(reg & SPI_FPR_WPE)) { + printk(BIOS_ERR, "ERROR: Unable to set SPI FPR %d\n", fpr); + return -1; + } + + printk(BIOS_INFO, "%s: FPR %d is enabled for range 0x%08x-0x%08x\n", + __func__, fpr, start, end); + return 0; +} diff --git a/src/soc/intel/common/spi.h b/src/soc/intel/common/spi.h new file mode 100644 index 0000000..4e6c118 --- /dev/null +++ b/src/soc/intel/common/spi.h @@ -0,0 +1,45 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2016 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define SPI_FPR_SHIFT 12 +#define SPI_FPR_MASK 0x7fff +#define SPI_FPR_BASE_SHIFT 0 +#define SPI_FPR_LIMIT_SHIFT 16 +#define SPI_FPR_RPE (1 << 15) /* Read Protect */ +#define SPI_FPR_WPE (1 << 31) /* Write Protect */ +#define SPI_FPR(base, limit) \ + (((((limit) >> SPI_FPR_SHIFT) & SPI_FPR_MASK) << SPI_FPR_LIMIT_SHIFT) |\ + ((((base) >> SPI_FPR_SHIFT) & SPI_FPR_MASK) << SPI_FPR_BASE_SHIFT)) + +struct fpr_info { + /* Offset of first FPR register */ + uintptr_t base; + /* Maximum number of FPR registers */ + uint8_t max; +}; + +/* + * SoC is expected to implement this function to provide address of first FPR + * register and max count of FPR registers. + * + * On success return 0 else -1. + */ +int spi_get_fpr_info(struct fpr_info *info); + +/* + * Protect range of SPI flash defined by [start, start+size-1] using Flash + * Protected Range(FPR) register if available. + */ +int spi_flash_protect(u32 start, u32 size);