aboutsummaryrefslogtreecommitdiff
path: root/libstb
diff options
context:
space:
mode:
authorClaudio Carvalho <cclaudio@linux.vnet.ibm.com>2016-11-28 01:08:07 -0200
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-11-29 18:17:02 +1100
commit454d0be05bcd1de6ea263c9b625a63a57a6098fc (patch)
treeadb6c41f4f3001bc4229e7cc3b5ac249f2301fca /libstb
parent71b88229c99c36ccfdbaaa50c851343f95c24320 (diff)
downloadskiboot-454d0be05bcd1de6ea263c9b625a63a57a6098fc.zip
skiboot-454d0be05bcd1de6ea263c9b625a63a57a6098fc.tar.gz
skiboot-454d0be05bcd1de6ea263c9b625a63a57a6098fc.tar.bz2
tpm_i2c_nuvoton: handle errors after checking the tpm fifo status
The functions tpm_is_expecting() and tpm_is_data_avail() ignore the errors returned by the tpm-i2c interface. This adds code to handle erros after checking the tpm fifo status. The tpm_is_expecting() and tpm_is_data_avail() functions are replaced by tpm_wait_for_fifo_status(). Fixes: 56ad053c3e8bf0764ad5878cb018f00a389d30cf Signed-off-by: Claudio Carvalho <cclaudio@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'libstb')
-rw-r--r--libstb/drivers/tpm_i2c_nuvoton.c152
1 files changed, 86 insertions, 66 deletions
diff --git a/libstb/drivers/tpm_i2c_nuvoton.c b/libstb/drivers/tpm_i2c_nuvoton.c
index 0c99431..62236e4 100644
--- a/libstb/drivers/tpm_i2c_nuvoton.c
+++ b/libstb/drivers/tpm_i2c_nuvoton.c
@@ -77,30 +77,6 @@ static bool tpm_check_status(uint8_t status, uint8_t mask, uint8_t expected)
return ((status & mask) == expected);
}
-static int tpm_read_sts_reg_valid(uint8_t* value)
-{
- int polls, rc;
-
- for(polls=0; polls<=MAX_STSVALID_POLLS; polls++) {
- rc = tpm_status_read_byte(TPM_STS, value);
- if (rc < 0)
- return rc;
- if (tpm_check_status(*value, TPM_STS_VALID, TPM_STS_VALID))
- return 0;
- /* Wait TPM STS register be settled */
- time_wait_ms(5);
- }
- value = 0;
- /**
- * @fwts-label TPMValidBitTimeout
- * @fwts-advice The valid bit of the tpm status register is taking
- * longer to be settled. Either the wait time needs to be increased
- * or the TPM device is not functional.
- */
- prlog(PR_ERR, "TPM: valid bit not settled. Timeout.\n");
- return STB_TPM_TIMEOUT;
-}
-
static int tpm_wait_for_command_ready(void)
{
int rc, delay;
@@ -168,39 +144,59 @@ static int tpm_set_command_ready(void)
return STB_TPM_TIMEOUT;
}
-static bool tpm_is_expecting(int* rc)
+static int tpm_wait_for_fifo_status(uint8_t mask, uint8_t expected)
{
- uint8_t value = 0;
- *rc = tpm_read_sts_reg_valid(&value);
- if (*rc < 0)
- return false;
- if (tpm_check_status(value, TPM_STS_EXPECT, TPM_STS_EXPECT))
- return true;
- return false;
-}
+ int retries, rc;
+ uint8_t status;
-static bool tpm_is_data_avail(int* rc)
-{
- uint8_t value = 0;
-
- *rc = tpm_read_sts_reg_valid(&value);
- if (*rc < 0)
- return false;
- if (tpm_check_status(value, TPM_STS_DATA_AVAIL, TPM_STS_DATA_AVAIL))
- return true;
- return false;
+ for(retries = 0; retries <= MAX_STSVALID_POLLS; retries++) {
+ rc = tpm_status_read_byte(TPM_STS, &status);
+ if (rc < 0) {
+ /**
+ * @fwts-label TPMReadFifoStatus
+ * @fwts-advice Either the tpm device or the tpm-i2c
+ * interface doesn't seem to be working properly. Check
+ * the return code (rc) for further details.
+ */
+ prlog(PR_ERR, "NUVOTON: fail to read fifo status: "
+ "mask %x, expected %x, rc=%d\n", mask, expected,
+ rc);
+ return STB_DRIVER_ERROR;
+ }
+ if (tpm_check_status(status, mask, expected))
+ return 0;
+ /* Wait TPM STS register be settled */
+ time_wait_ms(5);
+ }
+ return STB_TPM_TIMEOUT;
}
-static int tpm_poll_for_data_avail(void)
+static int tpm_wait_for_data_avail(void)
{
int delay, rc;
+ uint8_t status;
for (delay = 0; delay < TPM_TIMEOUT_A;
delay += TPM_TIMEOUT_INTERVAL) {
- if (tpm_is_data_avail(&rc)) {
+
+ rc = tpm_status_read_byte(TPM_STS, &status);
+ if (rc < 0) {
+ /**
+ * @fwts-label TPMReadDataAvail
+ * @fwts-advice Either the tpm device or the tpm-i2c
+ * interface doesn't seem to be working properly. Check
+ * the return code (rc) for further details.
+ */
+ prlog(PR_ERR, "NUVOTON: fail to read sts.dataAvail, "
+ "rc=%d\n", rc);
+ return STB_DRIVER_ERROR;
+ }
+ if (tpm_check_status(status,
+ TPM_STS_VALID | TPM_STS_DATA_AVAIL,
+ TPM_STS_VALID | TPM_STS_DATA_AVAIL)) {
DBG("---- read FIFO. Data available. delay=%d/%d\n",
delay, TPM_TIMEOUT_A);
- return rc;
+ return 0;
}
time_wait_ms(TPM_TIMEOUT_INTERVAL);
}
@@ -210,7 +206,7 @@ static int tpm_poll_for_data_avail(void)
* longer to be settled. Either the wait time need to be increased or
* the TPM device is not functional.
*/
- prlog(PR_ERR, "TPM: read FIFO. Polling timeout, delay=%d/%d\n",
+ prlog(PR_ERR, "NUVOTON: timeout on sts.dataAvail, delay=%d/%d\n",
delay, TPM_TIMEOUT_A);
return STB_TPM_TIMEOUT;
}
@@ -291,14 +287,19 @@ static int tpm_write_fifo(uint8_t* buf, size_t buflen)
if (rc < 0)
return rc;
- if (!tpm_is_expecting(&rc)) {
+ rc = tpm_wait_for_fifo_status(TPM_STS_VALID | TPM_STS_EXPECT,
+ TPM_STS_VALID | TPM_STS_EXPECT);
+ if (rc == STB_DRIVER_ERROR)
+ return rc;
+ if (rc == STB_TPM_TIMEOUT) {
/**
- * @fwts-label TPMWriteFifoOverflow1
+ * @fwts-label TPMWriteFifoNotExpecting
* @fwts-advice The write to the TPM FIFO overflowed,
- * the TPM is not expecting more data. This indicates a bug
- * in the TPM device driver.
+ * the TPM is not expecting more data. This indicates a
+ * bug in the TPM device driver.
*/
- prlog(PR_ERR, "TPM: write FIFO overflow1\n");
+ prlog(PR_ERR, "NUVOTON: write FIFO overflow, not expecting "
+ "more data\n");
return STB_TPM_OVERFLOW;
}
} while (curByte < length);
@@ -318,20 +319,34 @@ static int tpm_write_fifo(uint8_t* buf, size_t buflen)
DBG("%s write FIFO sent last byte, rc=%d\n",
(rc) ? "!!!!" : "----", TPM_TIMEOUT_D, rc);
+ if (rc < 0) {
+ /**
+ * @fwts-label TPMWriteFifo
+ * @fwts-advice The tpm-i2c interface doesn't seem to be
+ * working properly. Check the return code (rc) for
+ * further details.
+ */
+ prlog(PR_ERR, "NUVOTON: fail to write fifo (last byte), "
+ "curByte=%zd, rc=%d\n", curByte, rc);
+ return STB_DRIVER_ERROR;
+ }
+ rc = tpm_wait_for_fifo_status(TPM_STS_VALID | TPM_STS_EXPECT,
+ TPM_STS_VALID | TPM_STS_EXPECT);
+ if (rc == STB_DRIVER_ERROR)
+ return rc;
if (rc == 0) {
- if (tpm_is_expecting(&rc)) {
- /**
- * @fwts-label TPMWriteFifoOverflow2
- * @fwts-advice The write to the TPM FIFO overflowed.
- * It is expecting more data even though we think we
- * are done. This indicates a bug in the TPM device
- * driver.
- */
- prlog(PR_ERR, "TPM: write FIFO overflow2\n");
- return STB_TPM_OVERFLOW;
- }
+ /**
+ * @fwts-label TPMWriteFifoExpecting
+ * @fwts-advice The write to the TPM FIFO overflowed.
+ * It is expecting more data even though we think we
+ * are done. This indicates a bug in the TPM device
+ * driver.
+ */
+ prlog(PR_ERR, "TPM: write FIFO overflow, expecting "
+ "more data\n");
+ return STB_TPM_OVERFLOW;
}
- return rc;
+ return 0;
}
static int tpm_read_fifo(uint8_t* buf, size_t* buflen)
@@ -341,7 +356,7 @@ static int tpm_read_fifo(uint8_t* buf, size_t* buflen)
uint8_t* bytePtr = (uint8_t*)buf;
uint8_t* curBytePtr = NULL;
- rc = tpm_poll_for_data_avail();
+ rc = tpm_wait_for_data_avail();
if (rc < 0)
goto error;
@@ -377,7 +392,12 @@ static int tpm_read_fifo(uint8_t* buf, size_t* buflen)
(rc) ? "!!!!" : "----", curByte, rc);
if (rc < 0)
goto error;
- } while (tpm_is_data_avail(&rc));
+ rc = tpm_wait_for_fifo_status(
+ TPM_STS_VALID | TPM_STS_DATA_AVAIL,
+ TPM_STS_VALID | TPM_STS_DATA_AVAIL);
+ if (rc == STB_DRIVER_ERROR)
+ goto error;
+ } while (rc == 0);
*buflen = curByte;
return 0;