summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2015-08-14 18:33:09 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-08-21 20:08:59 +0000
commit0bb856d9e8276f8c36c777d3022a9323b773b432 (patch)
treee9244d0613e8f5471b188ecaa45ff279249da103
parentee6663563d721b21b3686f6744424d40efd0d34d (diff)
downloadchrome-ec-0bb856d9e8276f8c36c777d3022a9323b773b432.tar.gz
cr50: add tpm response processing.
This patch closes the loop of processing TPM commands, the response generated by ExecCommand() is placed in the buffer to be returned through FIFO read accesses. State machine and register states are updated as per TCG Platform Specification. A lot of debug output is generated, this is useful for debugging, will be filtered eventually. BRANCH=none BUG=chrome-os-partner:43025 TEST=with the appropriate tpm2 and trunks patches in place trunksd successfully initializes the CR50, sending such commands as Startup, GetCapability (three times) and SelfTest. Change-Id: Ibbd952b53930e4530461db7dcdbc510a8022412c Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/293910 Reviewed-by: Utkarsh Sanghi <usanghi@chromium.org>
-rw-r--r--common/tpm_registers.c63
1 files changed, 54 insertions, 9 deletions
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index edd67e6719..543d9c8a29 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -99,6 +99,18 @@ enum tpm_sts_bits {
response_retry = (1 << 1),
};
+static void set_tpm_state(enum tpm_states state)
+{
+ CPRINTF("state transition from %d to %d\n", tpm_.state, state);
+ tpm_.state = state;
+
+ if (state == tpm_state_idle) {
+ /* Make sure FIFO is empty. */
+ tpm_.fifo_read_index = 0;
+ tpm_.fifo_write_index = 0;
+ }
+}
+
/*
* Some TPM registers allow writing of only exactly one bit. This helper
* function allows to verify that a value is compliant with this
@@ -160,9 +172,7 @@ static void access_reg_write(uint8_t data)
}
tpm_.regs.access &= ~active_locality;
/* No matter what we do, fall into idle state. */
- tpm_.state = tpm_state_idle;
- tpm_.fifo_read_index = 0;
- tpm_.fifo_write_index = 0;
+ set_tpm_state(tpm_state_idle);
break;
default:
@@ -180,7 +190,7 @@ static void sts_reg_write_cr(void)
{
switch (tpm_.state) {
case tpm_state_idle:
- tpm_.state = tpm_state_ready;
+ set_tpm_state(tpm_state_ready);
tpm_.regs.sts |= command_ready;
break;
case tpm_state_ready:
@@ -189,7 +199,7 @@ static void sts_reg_write_cr(void)
case tpm_state_completing_cmd:
case tpm_state_executing_cmd:
case tpm_state_receiving_cmd:
- tpm_.state = tpm_state_idle;
+ set_tpm_state(tpm_state_idle);
tpm_.regs.sts &= ~command_ready;
break;
}
@@ -206,7 +216,7 @@ static void sts_reg_write_tg(void)
case tpm_state_receiving_cmd:
if (!(tpm_.state & expect)) {
/* This should trigger actual command execution. */
- tpm_.state = tpm_state_executing_cmd;
+ set_tpm_state(tpm_state_executing_cmd);
task_set_event(TASK_ID_TPM, TASK_EVENT_WAKE, 0);
}
break;
@@ -284,7 +294,7 @@ static void fifo_reg_write(const uint8_t *data, uint32_t data_size)
* access.
*/
if ((tpm_.state == tpm_state_ready) && (tpm_.fifo_write_index == 0))
- tpm_.state = tpm_state_receiving_cmd;
+ set_tpm_state(tpm_state_receiving_cmd);
if (tpm_.state != tpm_state_receiving_cmd) {
CPRINTF("%s: ignoring data in state %d\n",
@@ -296,7 +306,7 @@ static void fifo_reg_write(const uint8_t *data, uint32_t data_size)
CPRINTF("%s: receive buffer overflow: %d in addition to %d\n",
__func__, data_size, tpm_.fifo_write_index);
tpm_.fifo_write_index = 0;
- tpm_.state = tpm_state_ready;
+ set_tpm_state(tpm_state_ready);
return;
}
@@ -325,6 +335,11 @@ static void fifo_reg_write(const uint8_t *data, uint32_t data_size)
void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
{
uint32_t i;
+ uint32_t idata;
+
+ memcpy(&idata, data, 4);
+ CPRINTF("%s(0x%06x, %d %x)\n", __func__, regaddr, data_size, idata);
+
switch (regaddr) {
case TPM_ACCESS:
/* This is a one byte register, ignore extra data, if any */
@@ -346,8 +361,24 @@ void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
}
+void fifo_reg_read(uint8_t *dest, uint32_t data_size)
+{
+ uint32_t still_in_fifo = tpm_.fifo_write_index -
+ tpm_.fifo_read_index;
+
+ data_size = MIN(data_size, still_in_fifo);
+ memcpy(dest,
+ tpm_.regs.data_fifo + tpm_.fifo_read_index,
+ data_size);
+
+ tpm_.fifo_read_index += data_size;
+ if (tpm_.fifo_write_index == tpm_.fifo_read_index)
+ tpm_.regs.sts &= ~(data_avail | command_ready);
+}
+
void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
{
+ CPRINTF("%s(0x%06x, %d)", __func__, regaddr, data_size);
switch (regaddr) {
case TPM_DID_VID:
copy_bytes(dest, data_size, (GOOGLE_DID << 16) | GOOGLE_VID);
@@ -362,18 +393,23 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
copy_bytes(dest, data_size, tpm_.regs.access);
break;
case TPM_STS:
+ CPRINTF(" %x", tpm_.regs.sts);
copy_bytes(dest, data_size, tpm_.regs.sts);
break;
+ case TPM_DATA_FIFO:
+ fifo_reg_read(dest, data_size);
+ break;
default:
CPRINTS("%s(0x%06x, %d) => ??", __func__, regaddr, data_size);
return;
}
+ CPRINTF("\n");
}
static void tpm_init(void)
{
- tpm_.state = tpm_state_idle;
+ set_tpm_state(tpm_state_idle);
tpm_.regs.access = tpm_reg_valid_sts;
tpm_.regs.sts = (tpm_family_tpm2 << tpm_family_shift) |
(64 << burst_count_shift) | sts_valid;
@@ -401,5 +437,14 @@ void tpm_task(void)
tpm_.regs.data_fifo,
&response_size,
&response);
+ CPRINTF("got %d bytes in response\n", response_size);
+ if (response_size &&
+ (response_size <= sizeof(tpm_.regs.data_fifo))) {
+ memcpy(tpm_.regs.data_fifo, response, response_size);
+ tpm_.fifo_read_index = 0;
+ tpm_.fifo_write_index = response_size;
+ tpm_.regs.sts |= data_avail;
+ set_tpm_state(tpm_state_completing_cmd);
+ }
}
}