Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/28697
Change subject: drivers/spi/winbond: Add function to lock flash's status register ......................................................................
drivers/spi/winbond: Add function to lock flash's status register
Add a new function pointer to lock down the status register. Allows to enable various write-protection schemes.
Change-Id: I90e0fcdcf531b53c0fc1ffcfdb3b5ab522f088f5 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/drivers/spi/spi_flash.c M src/drivers/spi/winbond.c M src/include/spi_flash.h 3 files changed, 107 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/97/28697/1
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index 9127a5d..577ce4b 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -432,6 +432,27 @@ return -1; }
+int spi_flash_enable_write_protect(const struct spi_flash *flash, + const enum spi_flash_status_reg_lockdown mode, + const bool non_volatile) +{ + int ret; + + if (!flash) + return -1; + + if (!flash->ops->enable_write_protect) { + printk(BIOS_WARNING, "SPI: Enabling write-protection is not " + "implemented for this vendor.\n"); + return 0; + } + + ret = flash->ops->enable_write_protect(flash, mode, non_volatile); + if (ret != 0) + printk(BIOS_ERR, "SPI: Failed to enable write-protection\n"); + return ret; +} + int spi_flash_is_write_protected(const struct spi_flash *flash, const struct region *region) { diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c index 0272d5a..7b751f7 100644 --- a/src/drivers/spi/winbond.c +++ b/src/drivers/spi/winbond.c @@ -515,6 +515,63 @@ return ret; }
+/* + * Available on all devices. + * Protect a region starting from start of flash or end of flash. + * The caller must provide a valid protected region size. + * SEC isn't supported and set to zero. + * Write block protect bits to Status/Status2 Reg and leave status register + * unlocked. + * + * @param flash The handle to flash working on + * @param region The region to write protect + * @param non_volatile Write status register non-volatile + * + * Returns: + * -1 on error + * 0 on success + */ + +static int +winbond_enable_write_protect(const struct spi_flash *flash, + const enum spi_flash_status_reg_lockdown mode, + const bool non_volatile) +{ + const struct winbond_spi_flash_params *params; + u8 mask, val; + int ret; + + params = (const struct winbond_spi_flash_params *)flash->driver_private; + if (!params) + return -1; + + if (mode > SPI_WRITE_PROTECTION_PERMANENT) + return -1; + + if (params->bp_bits == 3) { + val = (union status_reg1_bp3){ .srp0 = !!(mode & 1) }.u; + mask = (union status_reg1_bp3){ .srp0 = 1 }.u; + } else { + val = (union status_reg1_bp4){ .srp0 = !!(mode & 1) }.u; + mask = (union status_reg1_bp4){ .srp0 = 1 }.u; + } + + ret = winbond_flash_cmd_status(flash, 0, mask, val, non_volatile); + if (ret) + return ret; + + val = (union status_reg2){ .srp1 = !!(mode & 2) }.u; + mask = (union status_reg2){ .srp1 = 1 }.u; + + ret = winbond_flash_cmd_status(flash, 1, mask, val, non_volatile); + if (ret) + return ret; + + printk(BIOS_DEBUG, "WINBOND: locked flash status register, mode %u\n", + mode); + return 0; +} + static const struct spi_flash_ops spi_flash_ops = { .write = winbond_write, .erase = spi_flash_cmd_erase, @@ -526,6 +583,7 @@ #endif .get_write_protection = winbond_get_write_protection, .set_write_protection = winbond_set_write_protection, + .enable_write_protect = winbond_enable_write_protect, };
int spi_flash_probe_winbond(const struct spi_slave *spi, u8 *idcode, diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index 3f0c0fa..55c7992 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -26,6 +26,13 @@
struct spi_flash;
+enum spi_flash_status_reg_lockdown { + SPI_WRITE_PROTECTION_NONE = 0, + SPI_WRITE_PROTECTION_PIN, + SPI_WRITE_PROTECTION_REBOOT, + SPI_WRITE_PROTECTION_PERMANENT +}; + /* * Representation of SPI flash operations: * read: Flash read operation. @@ -63,6 +70,10 @@ int (*set_write_protection)(const struct spi_flash *flash, const struct region *region, const bool non_volatile); + + int (*enable_write_protect)(const struct spi_flash *flash, + const enum spi_flash_status_reg_lockdown mode, + const bool non_volatile); };
struct spi_flash { @@ -119,6 +130,23 @@ int spi_flash_status(const struct spi_flash *flash, u8 *reg);
/* + * Lock down the the vendor dependent SPI flash status register. + * Call this after setting the flash write protection bits. + * + * @param flash : A SPI flash device + * @param mode: The lockdown-mode to apply + * @param non_volatile: Write status register non-volatile + * + * Returns: + * -1 on error + * 0 on success + */ + +int spi_flash_enable_write_protect(const struct spi_flash *flash, + const enum spi_flash_status_reg_lockdown mode, + const bool non_volatile); + +/* * Return the vendor dependent SPI flash write protection state. * @param flash : A SPI flash device * @param region: A subregion of the device's region