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

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I90e0fcdcf531b53c0fc1ffcfdb3b5ab522f088f5 </div>
<div style="display:none"> Gerrit-Change-Number: 28697 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>