Christian Walter has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/34106 )
Change subject: src/drivers/crb: Add CRB Driver for TPM Support ......................................................................
src/drivers/crb: Add CRB Driver for TPM Support
Add the Command Response Buffer which is defined in the TPM 2.0 Specs. CRB can be specified with MAINBOARD_HAS_CRB_TPM, even though it is actually SoC specific.
Untested and WIP.
Change-Id: I477e45963fe3cdbc02cda9ae99c19142747e4b46 Signed-off-by: Christian Walter christian.walter@9elements.com --- A src/drivers/crb/Kconfig A src/drivers/crb/Makefile.inc A src/drivers/crb/tis.c A src/drivers/crb/tpm.c A src/drivers/crb/tpm.h 5 files changed, 257 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/06/34106/1
diff --git a/src/drivers/crb/Kconfig b/src/drivers/crb/Kconfig new file mode 100644 index 0000000..831af3d --- /dev/null +++ b/src/drivers/crb/Kconfig @@ -0,0 +1,5 @@ +config CRB_TPM + bool + help + CRB TPM driver is enabled! + diff --git a/src/drivers/crb/Makefile.inc b/src/drivers/crb/Makefile.inc new file mode 100644 index 0000000..3f12b36 --- /dev/null +++ b/src/drivers/crb/Makefile.inc @@ -0,0 +1,5 @@ +bootblock-$(CONFIG_CRB_TPM) += tis.c tpm.c +verstage-$(CONFIG_CRB_TPM) += tis.c tpm.c +romstage-$(CONFIG_CRB_TPM) += tis.c tpm.c +ramstage-$(CONFIG_CRB_TPM) += tis.c tpm.c +postcar-$(CONFIG_CRB_TPM) += tis.c tpm.c diff --git a/src/drivers/crb/tis.c b/src/drivers/crb/tis.c new file mode 100644 index 0000000..04ae9e6 --- /dev/null +++ b/src/drivers/crb/tis.c @@ -0,0 +1,85 @@ +/* + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <arch/early_variables.h> +#include <console/console.h> +#include <security/tpm/tis.h> + +#include "tpm.h" + +static unsigned tpm_is_open CAR_GLOBAL; + +static const struct { + uint16_t vid; + uint16_t did; + const char *device_name; +} dev_map[] = { + { 0x15d1, 0x001b, "SLB9670" }, + { 0x1ae0, 0x0028, "CR50" }, +}; + +static const char *tis_get_dev_name(struct tpm2_info *info) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dev_map); i++) + if ((dev_map[i].vid == info->vendor_id) && + (dev_map[i].did == info->device_id)) + return dev_map[i].device_name; + return "Unknown"; +} + +int tis_open(void) +{ + if (car_get_var(tpm_is_open)) { + printk(BIOS_ERR, "%s called twice.\n" __func__); + return -1; + } + return 0; +} + +int tis_close(void) +{ + if (car_get_var(tpm_is_open)) { + + /* + * Do we need to do something here, like waiting for a + * transaction to stop? + */ + car_set_var(tpm_is_open, 0); + } + + return 0; +} + +int tis_init(void) +{ + struct tpm2_info info; + + // Wake TPM up (if necessary) + if (tpm2_init() != 0) + return -1; + + tpm2_get_info(&info); + + printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", + tis_get_dev_name(&info), info.revision); + + return 0; +} + + +int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, + uint8_t *recvbuf, size_t *rbuf_len) +{ + int len = tpm2_process_command(sendbuf, sbuf_size, recvbuf, *rbuf_len); + + if (len == 0) + return -1; + + *rbuf_len = len; + + return 0; +} diff --git a/src/drivers/crb/tpm.c b/src/drivers/crb/tpm.c new file mode 100644 index 0000000..b5393f7 --- /dev/null +++ b/src/drivers/crb/tpm.c @@ -0,0 +1,128 @@ +/*. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * This is a driver for a CRB Interface. + * + * The general flow looks like this: + * + * TPM starts in IDLE Mode + * + * IDLE --> READY --> Command Receiption + * ^ | + * | v + -- Cmd Complete <-- Command Execution + */ + +#include <timer.h> +#include <arch/early_variables.h> +#include <console/console.h> + +#include "tpm.h" + +#define CRB_CMD_TIMEOUT 1000 //DEBUG + +uint32_t crb_tpm2_cmd_buffer_size = 0; +uint64_t crb_tpm2_cmd_buffer_addr = 0; +uint32_t crb_tpm2_resp_buffer_size = 0; +uint64_t crb_tpm2_resp_buffer_addr = 0; + +/* + * tpm_is_idle + * + * Check if tpm is in idle mode + * return values: + * 1 if ready + * 0 if idle + * -1 otherwise + */ +static int tpm2_state(void) +{ + struct stopwatch sw; + uint32_t regValue = 0xFFFFFFFF; + + // Set up a timer which breaks the loop after timeout + stopwatch_init_msecs_expire(&sw, CRB_CMD_TIMEOUT); + + while (1) { + // Now check if the TPM is in IDLE mode + regValue = read32(CRB_REG(0, CRB_REG_STATUS)); + if ((regValue && CRB_REG_STATUS_IDLE) == 0x01) { + printk(BIOS_INFO, "TPM is in idle state.\n"); + return 0; + } + + if ((regValue && (CRB_REG_STATUS_IDLE || CRB_REG_STATUS_ERROR)) == 0x00) { + printk(BIOS_INFO, "TPM is in ready state\n"); + return 1; + } + + if (stopwatch_expired(&sw)) + return -1; + } + + return -1; +} + +/* TPM should be ready to receive here */ +static void write_command(const void *tpm2_command, size_t command_size) +{ + +} + +/* TPM should be done so that we can copy the response over */ +static void read_commnad(void *tpm2_response, size_t max_response) +{ + +} + +/* + * tpm2_init + * + * Even though the TPM does not need an initialization we check + * if the TPM responds and is in IDLE mode, which should be the + * normal bring up mode. + * + */ +int tpm2_init(void) +{ + // Check if TPM is in idle state when it powers on. + if (tpm2_set_ready() == -1) { + printk(BIOS_ERR, "TPM CRB Init failed.\n"); + // Todo - set it to idle and retry + return -1; + } + printk(BIOS_INFO, "TPM initialized successfully"); + + // Fetch Information from the TPM + + return 0; +} + +/* + * tpm2_process_command + */ +size_t tpm2_process_command(const void *tpm2_command, size_t command_size, + void *tpm2_response, size_t max_response) +( + // Check device state + + // Write to Command Buffer + + // Poll for Response + + // Copy Response + + // Clear Bits +) + +/* + * tp2_get_info + * + * Returns information about the TPM + * + */ +void tpm2_get_info(struct tpm2_info *tpm2_info) +{ + //TODO +} diff --git a/src/drivers/crb/tpm.h b/src/drivers/crb/tpm.h new file mode 100644 index 0000000..05735c1 --- /dev/null +++ b/src/drivers/crb/tpm.h @@ -0,0 +1,34 @@ +/* + * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * This is a driver for a Command Response Buffer Interface + */ + +/* CRB driver */ +/* address of locality 0 (CRB) */ +#define TPM_CRB_BASE_ADDRESS 0xfed40000 + +#define CRB_REG(LOCTY, REG) \ + (void *)(TPM_CRB_BASE_ADDRESS + (LOCTY << 12) + REG) + +/* hardware registers */ +#define CRB_REG_REQUEST 0x00 +#define CRB_REG_STATUS 0x04 +#define CRB_REG_CANCEL 0x08 +#define CRB_REG_START 0x0C +#define CRB_REG_INT_CTRL 0x10 +#define CRB_REG_CMD_SIZE 0x18 +#define CRB_REG_CMD_ADDR 0x1C +#define CRB_REG_RESP_SIZE 0x24 +#define CRB_REG_RESP_ADDR 0x28 + +/*REQUEST Register related */ +#define CRB_REG_REQUEST_CMD_RDY 0x01 +#define CRB_REG_REQUEST_GO_IDLE 0x02 + +/* STATUS Register related */ +#define CRB_REG_STATUS_ERROR 0x01 +#define CRB_REG_STATUS_IDLE 0x02 +