diff options
author | Scott <scollyer@chromium.org> | 2016-08-23 14:46:52 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-09-05 23:22:16 -0700 |
commit | 7edd3827cf9d2174bc9d173c878379e0ad81c990 (patch) | |
tree | 82c2887b5f547851c7f606edf90ac67b6e771623 /common | |
parent | ef4ccb2318cafb040be782bffac6f2e836e17961 (diff) | |
download | chrome-ec-7edd3827cf9d2174bc9d173c878379e0ad81c990.tar.gz |
Cr50: I2CS TPM: Changes to support fifo and version registers read
This CL adds support for reading of TPM fifo registers. Since I2C does
not provide means to communicate how many bytes the host wants to read
there must be some handshake involved between the host and Cr50.
The method added by this CL to allow Host reads of the TPM fifo
assumes the following steps:
1. Host reads burstcount from Cr50 (which will be set to default 63)
2. Host reads 1st 10 bytes of the TPM response.
3. Cr50 will copy MIN(burstcount, msg_len) bytes into its I2CS HW fifo
4. Host computes msg_len and calculates amount of data still buffered
5. Host does a TPM fifo read of buffered data only
(The following steps are repeated until the response read is complete)
6. Host reads burstcount from STS register.
7. Host issues read of burscount bytes from TPM fifo
8. I2CS will copy burstcount amount of bytes in to I2CS HW fifo
9. TPM layer sets burstcount to MIN(63, remaining msg bytes)
The version register is treated similar to a fifo access. The data
written or the number of bytes is a don't care, but there must be
at least one byte of data written with the version register write.
In the case of reads, the host must read burstcount bytes of the
version register. If burstcount is longer than the Cr50 version string
there is no issue because the version register read function always
returns the number of bytes requested, stuffing in 0s once the end of
the version string is reached.
BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Created test code in coreboot that exercises TPM register reads and
writes. In addition, created a means to spoof a TPM cmd send and
response read by Host. For these tests the header length is defined as
10 bytes and used 3 different payload lengths. The results for a
payload length of 256 and 39 (message < 63) are shown below. Note the
0xaa and 0x55 have been inserted by the TPM spoof code on the host to
mark the end of the header.
=================================================
Cr50 TPM Register Read tests
TPM Access = 0x0
TPM2 STS = 0x4003f80
TPM2 DID_VID = 0x281ae0
DID = 0x28, VID = 0x1ae0
Ver segment read 1, ret = 0
Version: B2:0 RO_A:0.0.1/84e2dde7 RW_A:0.0.1/cr50_v1.1.5151-acaef21+
=================================================
TPM Cmd: 266 bytes, Hdr = 10, Payload = 256 (last = ff)
TPM STS: Sending command_ready
fifo wr: burstcount = 63
fifo wr: Sent TPM Cmd: len = 266 bytes
TPM STS: Sending TPM GO
TPM STS: data_avail set
TPM STS: 04 00 3f d0: burst = 63
fifo rd: Msg_len = 266
fifo rd: Hdr Len = 10, fifo_adjust = 53
fifo rd: Drained Cr50 HW fifo of 53 bytes
fifo rd: burst = 63
fifo rd: burst = 63
fifo rd: burst = 63
fifo rd: burst = 14
fifo rd: complete 266 byte msg read
[0000]: 00 00 00 00 01 0a 00 00 aa 55 00 01 02 03 04 05
[0010]: 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
[0020]: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
[0030]: 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35
[0040]: 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45
[0050]: 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55
[0060]: 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65
[0070]: 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
[0080]: 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85
[0090]: 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95
[00a0]: 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5
[00b0]: a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5
[00c0]: b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
[00d0]: c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5
[00e0]: d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5
[00f0]: e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5
[0100]: f6 f7 f8 f9 fa fb fc fd fe ff 00 00 00 00 00 00
=================================================
TPM Cmd: 49 bytes, Hdr = 10, Payload = 39 (last = 26)
TPM STS: Sending command_ready
fifo wr: burstcount = 63
fifo wr: Sent TPM Cmd: len = 49 bytes
TPM STS: Sending TPM GO
TPM STS: data_avail set
TPM STS: 04 00 3f d0: burst = 63
fifo rd: Msg_len = 49
fifo rd: Hdr Len = 10, fifo_adjust = 39
fifo rd: Drained Cr50 HW fifo of 39 bytes
fifo rd: complete 49 byte msg read
[0000]: 02 00 00 00 00 31 00 00 aa 55 00 01 02 03 04 05
[0010]: 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
[0020]: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
[0030]: 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Change-Id: I0e05156d6012c6dc86844e4c0ea80cc04f45734a
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/374528
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/i2cs_tpm.c | 20 | ||||
-rw-r--r-- | common/tpm_registers.c | 13 |
2 files changed, 28 insertions, 5 deletions
diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c index dfc89ea822..87a075a9a9 100644 --- a/common/i2cs_tpm.c +++ b/common/i2cs_tpm.c @@ -74,7 +74,7 @@ static const struct i2c_tpm_reg_map i2c_to_tpm[] = { {6, 4, 0xf00}, /* TPM DID VID */ {0xa, 4, 0x14}, /* TPM TPM_INTF_CAPABILITY */ {0xe, 1, 0xf04}, /* TPM RID */ - {0xf, 4, 0xf90}, /* TPM_FW_VER */ + {0xf, 0, 0xf90}, /* TPM_FW_VER */ }; static void wr_complete_handler(void *i2cs_data, size_t i2cs_data_size) @@ -150,6 +150,24 @@ static void wr_complete_handler(void *i2cs_data, size_t i2cs_data_size) * burst size field of the tpm status register. */ reg_size = tpm_get_burst_size(); + + /* For TPM fifo reads, if there is already data pending in the + * I2CS hw fifo, then don't read any more TPM fifo data until + * the I2CS hw fifo has been fully drained. + * + * The Host will only read only enough data to extract the full + * TPM message length. However, Cr50 will fill the I2CS hw fifo + * with 'burstsize' amount of bytes. The 2nd fifo access for a + * given TPM repsonse by the Host will extract the queued up + * data. Following this, the Host will then read 'burstcount' + * amount of data for subsequent fifo accesses until the + * response has been fully read. + * + */ + if (i2cs_get_read_fifo_buffer_depth()) + /* Data is already in the queue, just return */ + return; + /* * Now, this is a hack, but we are short on SRAM, so let's * reuse the receive buffer for the FIFO data sotrage. We know diff --git a/common/tpm_registers.c b/common/tpm_registers.c index 95071c10c9..615f7013bd 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -387,8 +387,6 @@ void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size) fifo_reg_write(data, data_size); break; case TPM_FW_VER: - /* Reload versions, in case something has been updated */ - set_version_string(); /* Reset read byte count */ tpm_fw_ver_index = 0; break; @@ -419,7 +417,7 @@ void fifo_reg_read(uint8_t *dest, uint32_t data_size) tpm_sts &= ~(burst_count_mask << burst_count_shift); if (tpm_.fifo_write_index == tpm_.fifo_read_index) { tpm_sts &= ~(data_avail | command_ready); - /* Birst size for the following write requests. */ + /* Burst size for the following write requests. */ tpm_sts |= 63 << burst_count_shift; } else { /* @@ -494,12 +492,19 @@ static void tpm_init(void) { set_tpm_state(tpm_state_idle); tpm_.regs.access = tpm_reg_valid_sts; + /* + * I2CS writes must limit the burstsize to 63 for fifo writes to work + * properly. For I2CS fifo writes the first byte is the I2C TPM address + * and the next up to 62 bytes are the data to write to that register. + */ tpm_.regs.sts = (tpm_family_tpm2 << tpm_family_shift) | - (64 << burst_count_shift) | sts_valid; + (63 << burst_count_shift) | sts_valid; /* TPM2 library functions. */ _plat__Signal_PowerOn(); + /* Create version string to be read by host */ + set_version_string(); /* * Make sure NV RAM metadata is initialized, needed to check |