<p>Vadim Bendebury has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22489">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">spi/tpm: claim locality just once during boot<br><br>All coreboot stages using TPM start with the same sequence: check if<br>locality is claimed, if so, release it by writing 'active locality'<br>bit, then try claiming it.<br><br>This is actually not a proper procedure: section "5.5.2.3.1 Command<br>Aborts" of "TCG PC Client Platform TPM Profile (PTP) Specification<br>Level 00 Revision 00.430 Family 2" lists overwriting active locality<br>status bit as a means of triggering TPM command abort.<br><br>On top of that, none of the coreboot stages releases locality, it is<br>enough to claim it once when device starts booting.<br><br>In fact, locality being active when the device is in verstage is most<br>likely due to delayed TPM reset processing by the Cr50 TPM: reset is<br>an asynchronous event, and is processed once current command<br>processing completes.<br><br>The proper procedure is to wait if locality is active until it is<br>released (which will happen when Cr50 processes reset) and then<br>proceed to claim it. This needs to happen only during verstage, other<br>stages using TPM are guaranteed has been claimed earlier.<br><br>BRANCH=gru<br>BUG=b:65867313<br><br>TEST=the new autotest triggering EC reset during key generation<br>     process does not cause boot failures on Fizz device any more.<br>     Below are times verstage had to wait:<br><br>  TPM ready after 3132 ms<br>  TPM ready after 22120 ms<br>  TPM ready after 4936 ms<br>  TPM ready after 6445 ms<br>  TPM ready after 11798 ms<br>  TPM ready after 27421 ms<br>  TPM ready after 4582 ms<br>  TPM ready after 7532 ms<br>  TPM ready after 27920 ms<br>  TPM ready after 3539 ms<br>  TPM ready after 12557 ms<br>  TPM ready after 6773 ms<br>  TPM ready after 1631 ms<br>  TPM ready after 197 ms<br>  TPM ready after 24330 ms<br>  TPM ready after 3241 ms<br><br>Change-Id: Iaee04f009bcde03712483e5e03de4a3441ea32b1<br>Signed-off-by: Vadim Bendebury <vbendeb@chromium.org><br>---<br>M src/drivers/spi/tpm/tpm.c<br>1 file changed, 41 insertions(+), 26 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/89/22489/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c<br>index c09462e..c506eb9 100644<br>--- a/src/drivers/spi/tpm/tpm.c<br>+++ b/src/drivers/spi/tpm/tpm.c<br>@@ -325,6 +325,7 @@<br>         return (status & TPM_STS_BURST_COUNT_MASK) >> TPM_STS_BURST_COUNT_SHIFT;<br> }<br> <br>+#if ENV_VERSTAGE<br> static uint8_t tpm2_read_access_reg(void)<br> {<br>  uint8_t access;<br>@@ -346,38 +347,50 @@<br>        uint8_t access;<br>       struct stopwatch sw;<br> <br>-      access = tpm2_read_access_reg();<br>      /*<br>-    * If active locality is set (maybe reset line is not connected?),<br>-    * release the locality and try again.<br>-        */<br>-  if (access & TPM_ACCESS_ACTIVE_LOCALITY) {<br>-               tpm2_write_access_reg(TPM_ACCESS_ACTIVE_LOCALITY);<br>-           access = tpm2_read_access_reg();<br>-     }<br>-<br>- /*<br>-    * If cr50 is doing a long crypto operation, it can take up to<br>-        * 30 seconds to get a valid status value back<br>+        * Locality is released by TPM reset.<br>+         *<br>+    * If locality is taken at this point, this could be due to the fact<br>+  * that the TPM is performing a long operation and has not processed<br>+  * reset request yet. We'll wait up to CR50_TIMEOUT_INIT_MS and see if<br>+    * it releases locality when reset is processed.<br>       */<br>   stopwatch_init_msecs_expire(&sw, CR50_TIMEOUT_INIT_MS);<br>-  while (!stopwatch_expired(&sw) && access != TPM_ACCESS_VALID)<br>+    do {<br>          access = tpm2_read_access_reg();<br>-     if (access != TPM_ACCESS_VALID) {<br>-            printk(BIOS_ERR, "Invalid reset status: %#x\n", access);<br>-           return 0;<br>-    }<br>+            if (access & TPM_ACCESS_ACTIVE_LOCALITY) {<br>+                       /*<br>+                    * Don't bombard the chip with traffic, let it keep<br>+                       * processing the command.<br>+                    */<br>+                  mdelay(2);<br>+                   continue;<br>+            }<br> <br>- tpm2_write_access_reg(TPM_ACCESS_REQUEST_USE);<br>-       access = tpm2_read_access_reg();<br>-     if (access != (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {<br>-             printk(BIOS_ERR, "Failed to claim locality 0, status: %#x\n",<br>-                     access);<br>-              return 0;<br>-    }<br>+            /*<br>+            * Ok, the locality is free, TPM must be reset, let's claim<br>+               * it.<br>+                */<br> <br>-       return 1;<br>+            tpm2_write_access_reg(TPM_ACCESS_REQUEST_USE);<br>+               access = tpm2_read_access_reg();<br>+             if (access != (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) {<br>+                     break;<br>+               }<br>+<br>+         printk(BIOS_INFO, "TPM ready after %ld ms\n",<br>+                     stopwatch_duration_msecs(&sw));<br>+<br>+                return 1;<br>+    } while (!stopwatch_expired(&sw));<br>+<br>+    printk(BIOS_ERR,<br>+            "Failed to claim locality 0 after %ld ms, status: %#x\n",<br>+          stopwatch_duration_msecs(&sw), access);<br>+<br>+        return 0;<br> }<br>+#endif<br> <br> /* Device/vendor ID values of the TPM devices this driver supports. */<br> static const uint32_t supported_did_vids[] = {<br>@@ -426,9 +439,11 @@<br> <br>  printk(BIOS_INFO, " done!\n");<br> <br>-  /* Claim locality 0. */<br>+#if ENV_VERSTAGE<br>+   /* Claim locality 0 if in verstage. */<br>        if (!tpm2_claim_locality())<br>           return -1;<br>+#endif<br> <br>        read_tpm_sts(&status);<br>    if ((status & TPM_STS_FAMILY_MASK) != TPM_STS_FAMILY_TPM_2_0) {<br></pre><p>To view, visit <a href="https://review.coreboot.org/22489">change 22489</a>. To unsubscribe, 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/22489"/><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: Iaee04f009bcde03712483e5e03de4a3441ea32b1 </div>
<div style="display:none"> Gerrit-Change-Number: 22489 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Bendebury <vbendeb@chromium.org> </div>