diff options
-rw-r--r-- | src/drivers/i2c/tpm/Kconfig | 16 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/Makefile.inc | 13 | ||||
-rw-r--r-- | src/drivers/i2c/tpm/tis_atmel.c | 132 |
3 files changed, 156 insertions, 5 deletions
diff --git a/src/drivers/i2c/tpm/Kconfig b/src/drivers/i2c/tpm/Kconfig index d35eb754b4..32e5fb4700 100644 --- a/src/drivers/i2c/tpm/Kconfig +++ b/src/drivers/i2c/tpm/Kconfig @@ -2,24 +2,38 @@ config I2C_TPM bool "I2C TPM" depends on TPM || TPM2 +config MAINBOARD_HAS_I2C_TPM_ATMEL + bool + default n + config MAINBOARD_HAS_I2C_TPM_CR50 bool default n choice prompt "I2C TPM Driver" + default I2C_TPM_ATMEL if MAINBOARD_HAS_I2C_TPM_ATMEL default I2C_TPM_CR50 if MAINBOARD_HAS_I2C_TPM_CR50 - default I2C_TPM_GENERIC if !MAINBOARD_HAS_I2C_TPM_CR50 + default I2C_TPM_GENERIC if !MAINBOARD_HAS_I2C_TPM_CR50 && !MAINBOARD_HAS_I2C_TPM_ATMEL depends on I2C_TPM config I2C_TPM_GENERIC bool "Generic I2C TPM Driver" +config I2C_TPM_ATMEL + bool "ATMEL I2C TPM Driver" + config I2C_TPM_CR50 bool "CR50 I2C TPM Driver" endchoice +config DRIVER_TIS_DEFAULT + bool + depends on I2C_TPM + default n if MAINBOARD_HAS_I2C_TPM_ATMEL + default y + config DRIVER_TPM_I2C_BUS hex "I2C TPM chip bus" default 0x9 # FIXME, workaround for Kconfig BS diff --git a/src/drivers/i2c/tpm/Makefile.inc b/src/drivers/i2c/tpm/Makefile.inc index 7fcfc78d56..afcb33bb93 100644 --- a/src/drivers/i2c/tpm/Makefile.inc +++ b/src/drivers/i2c/tpm/Makefile.inc @@ -1,8 +1,13 @@ -ramstage-$(CONFIG_I2C_TPM) += tis.c -romstage-$(CONFIG_I2C_TPM) += tis.c -verstage-$(CONFIG_I2C_TPM) += tis.c -bootblock-$(CONFIG_I2C_TPM) += tis.c +ramstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c +romstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c +verstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c +bootblock-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c + +ramstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c +romstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c +verstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c +bootblock-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c ramstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c romstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c diff --git a/src/drivers/i2c/tpm/tis_atmel.c b/src/drivers/i2c/tpm/tis_atmel.c new file mode 100644 index 0000000000..7d8b7a17b8 --- /dev/null +++ b/src/drivers/i2c/tpm/tis_atmel.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2017 Intel Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/early_variables.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> +#include <commonlib/endian.h> +#include <console/console.h> +#include <delay.h> +#include <device/i2c.h> +#include <endian.h> +#include <lib.h> +#include <tpm.h> +#include <timer.h> + +#define RECV_TIMEOUT (1 * 1000) /* 1 second */ +#define XMIT_TIMEOUT (1 * 1000) /* 1 second */ +#define SLEEP_DURATION 1000 /* microseconds */ + +struct tpm_output_header { + uint16_t tag; + uint32_t length; + uint32_t return_code; +} __attribute__ ((packed)); + +int tis_open(void) +{ + return 0; +} + +int tis_close(void) +{ + return 0; +} + +int tis_init(void) +{ + return 0; +} + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + size_t hdr_bytes; + struct tpm_output_header *header; + size_t max_recv_bytes; + size_t recv_bytes; + int status; + struct stopwatch sw; + + ASSERT(sbuf_size >= 10); + if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) { + /* Display the TPM command */ + if (sbuf_size >= 10) + printk(BIOS_DEBUG, "TPM Command: 0x%08x\n", + read_at_be32(sendbuf, sizeof(uint16_t) + + sizeof(uint32_t))); + hexdump(sendbuf, sbuf_size); + } + + /* Send the command to the TPM */ + stopwatch_init_msecs_expire(&sw, XMIT_TIMEOUT); + while (1) { + status = i2c_write_raw(CONFIG_DRIVER_TPM_I2C_BUS, + CONFIG_DRIVER_TPM_I2C_ADDR, (uint8_t *)sendbuf, + sbuf_size); + if ((status < 0) && (!stopwatch_expired(&sw))) + continue; + if (status < 0) + return status; + break; + } + + /* Read the TPM response header */ + max_recv_bytes = *rbuf_len; + ASSERT(max_recv_bytes >= sizeof(*header)); + hdr_bytes = sizeof(*header); + header = (struct tpm_output_header *)recvbuf; + stopwatch_init_msecs_expire(&sw, RECV_TIMEOUT); + do { + status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS, + CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, hdr_bytes); + if (status > 0) + break; + udelay(SLEEP_DURATION); + } while (!stopwatch_expired(&sw)); + if (status != sizeof(*header)) + return -1; + + /* Determine the number of bytes remaining */ + recv_bytes = min(be32_to_cpu(*(uint32_t *)&header->length), + max_recv_bytes); + + /* Determine if there is additional response data */ + if (recv_bytes > hdr_bytes) { + /* Display the TPM response */ + if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) + hexdump(recvbuf, hdr_bytes); + + /* Read the full TPM response */ + status = i2c_read_raw(CONFIG_DRIVER_TPM_I2C_BUS, + CONFIG_DRIVER_TPM_I2C_ADDR, recvbuf, recv_bytes); + if (status < 0) + return status; + } + + /* Return the number of bytes received */ + *rbuf_len = status; + + /* Display the TPM response */ + if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) { + printk(BIOS_DEBUG, "TPM Response: 0x%08x\n", + read_at_be32(recvbuf, sizeof(uint16_t) + + sizeof(uint32_t))); + hexdump(recvbuf, *rbuf_len); + } + + /* Successful transfer */ + return 0; +} |