drivers/spi/tpm: Improve error checking
This adds error checking in paths that previously ignored TPM communication errors. We hit this case occasionally during "Checking cr50 for pending updates"; previously we would go down this path and eventually time out using MAX_STATUS_TIMEOUT, which is 2 minutes. Now, we detect the failure and return with an error indication instead of timing out after a long time. The root cause of the communication error is an open issue. BUG=b:168090038 TEST=booted on volteer, observed error handling when "Checking cr50 for pending updates" fails. Signed-off-by: Caveh Jalali <caveh@chromium.org> Change-Id: Ia8a1202000abce1857ee694b06b1478e6b045069 Reviewed-on: https://review.coreboot.org/c/coreboot/+/45232 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jes Klinke <jbk@chromium.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
committed by
Patrick Georgi
parent
0f651650f3
commit
8274c2926f
@ -348,7 +348,7 @@ static int read_tpm_sts(uint32_t *status)
|
|||||||
return tpm2_read_reg(TPM_STS_REG, status, sizeof(*status));
|
return tpm2_read_reg(TPM_STS_REG, status, sizeof(*status));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_tpm_sts(uint32_t status)
|
static int __must_check write_tpm_sts(uint32_t status)
|
||||||
{
|
{
|
||||||
return tpm2_write_reg(TPM_STS_REG, &status, sizeof(status));
|
return tpm2_write_reg(TPM_STS_REG, &status, sizeof(status));
|
||||||
}
|
}
|
||||||
@ -688,9 +688,9 @@ union fifo_transfer_buffer {
|
|||||||
* Transfer requested number of bytes to or from TPM FIFO, accounting for the
|
* Transfer requested number of bytes to or from TPM FIFO, accounting for the
|
||||||
* current burst count value.
|
* current burst count value.
|
||||||
*/
|
*/
|
||||||
static void fifo_transfer(size_t transfer_size,
|
static int __must_check fifo_transfer(size_t transfer_size,
|
||||||
union fifo_transfer_buffer buffer,
|
union fifo_transfer_buffer buffer,
|
||||||
enum fifo_transfer_direction direction)
|
enum fifo_transfer_direction direction)
|
||||||
{
|
{
|
||||||
size_t transaction_size;
|
size_t transaction_size;
|
||||||
size_t burst_count;
|
size_t burst_count;
|
||||||
@ -711,18 +711,23 @@ static void fifo_transfer(size_t transfer_size,
|
|||||||
*/
|
*/
|
||||||
transaction_size = MIN(transaction_size, 64);
|
transaction_size = MIN(transaction_size, 64);
|
||||||
|
|
||||||
if (direction == fifo_receive)
|
if (direction == fifo_receive) {
|
||||||
tpm2_read_reg(TPM_DATA_FIFO_REG,
|
if (!tpm2_read_reg(TPM_DATA_FIFO_REG,
|
||||||
buffer.rx_buffer + handled_so_far,
|
buffer.rx_buffer + handled_so_far,
|
||||||
transaction_size);
|
transaction_size))
|
||||||
else
|
return 0;
|
||||||
tpm2_write_reg(TPM_DATA_FIFO_REG,
|
} else {
|
||||||
buffer.tx_buffer + handled_so_far,
|
if (!tpm2_write_reg(TPM_DATA_FIFO_REG,
|
||||||
transaction_size);
|
buffer.tx_buffer + handled_so_far,
|
||||||
|
transaction_size))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
handled_so_far += transaction_size;
|
handled_so_far += transaction_size;
|
||||||
|
|
||||||
} while (handled_so_far != transfer_size);
|
} while (handled_so_far != transfer_size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
||||||
@ -755,7 +760,10 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Let the TPM know that the command is coming. */
|
/* Let the TPM know that the command is coming. */
|
||||||
write_tpm_sts(TPM_STS_COMMAND_READY);
|
if (!write_tpm_sts(TPM_STS_COMMAND_READY)) {
|
||||||
|
printk(BIOS_ERR, "TPM_STS_COMMAND_READY failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TPM commands and responses written to and read from the FIFO
|
* TPM commands and responses written to and read from the FIFO
|
||||||
@ -769,10 +777,17 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
|||||||
* burst count or the maximum PDU size, whatever is smaller.
|
* burst count or the maximum PDU size, whatever is smaller.
|
||||||
*/
|
*/
|
||||||
fifo_buffer.tx_buffer = cmd_body;
|
fifo_buffer.tx_buffer = cmd_body;
|
||||||
fifo_transfer(command_size, fifo_buffer, fifo_transmit);
|
if (!fifo_transfer(command_size, fifo_buffer, fifo_transmit)) {
|
||||||
|
printk(BIOS_ERR, "fifo_transfer %zd command bytes failed\n",
|
||||||
|
command_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now tell the TPM it can start processing the command. */
|
/* Now tell the TPM it can start processing the command. */
|
||||||
write_tpm_sts(TPM_STS_GO);
|
if (!write_tpm_sts(TPM_STS_GO)) {
|
||||||
|
printk(BIOS_ERR, "TPM_STS_GO failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now wait for it to report that the response is ready. */
|
/* Now wait for it to report that the response is ready. */
|
||||||
expected_status_bits = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
|
expected_status_bits = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
|
||||||
@ -815,7 +830,11 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
|||||||
*/
|
*/
|
||||||
bytes_to_go = payload_size - 1 - HEADER_SIZE;
|
bytes_to_go = payload_size - 1 - HEADER_SIZE;
|
||||||
fifo_buffer.rx_buffer = rsp_body + HEADER_SIZE;
|
fifo_buffer.rx_buffer = rsp_body + HEADER_SIZE;
|
||||||
fifo_transfer(bytes_to_go, fifo_buffer, fifo_receive);
|
if (!fifo_transfer(bytes_to_go, fifo_buffer, fifo_receive)) {
|
||||||
|
printk(BIOS_ERR, "fifo_transfer %zd receive bytes failed\n",
|
||||||
|
bytes_to_go);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Verify that there is still data to read. */
|
/* Verify that there is still data to read. */
|
||||||
read_tpm_sts(&status);
|
read_tpm_sts(&status);
|
||||||
@ -840,7 +859,10 @@ size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Move the TPM back to idle state. */
|
/* Move the TPM back to idle state. */
|
||||||
write_tpm_sts(TPM_STS_COMMAND_READY);
|
if (!write_tpm_sts(TPM_STS_COMMAND_READY)) {
|
||||||
|
printk(BIOS_ERR, "TPM_STS_COMMAND_READY failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return payload_size;
|
return payload_size;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user