diff options
-rw-r--r-- | board/cr50/board.c | 2 | ||||
-rw-r--r-- | board/cr50/board.h | 3 | ||||
-rw-r--r-- | common/tpm_registers.c | 48 | ||||
-rw-r--r-- | core/cortex-m/ec.lds.S | 10 | ||||
-rw-r--r-- | include/tpm_registers.h | 11 |
5 files changed, 63 insertions, 11 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index 31a8d2fef1..c967871c8e 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -395,7 +395,7 @@ void sys_rst_asserted(enum gpio_signal signal) return; /* Re-initialize the TPM software state */ - task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0); + tpm_reset(); } void assert_sys_rst(void) diff --git a/board/cr50/board.h b/board/cr50/board.h index cc7589e750..7d11abd60d 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -136,9 +136,6 @@ void assert_ec_rst(void); void deassert_ec_rst(void); int is_ec_rst_asserted(void); -/* Event to request a reset/re-initialization of the TPM task */ -#define TPM_EVENT_RESET (TASK_EVENT_CUSTOM(1)) - #endif /* !__ASSEMBLER__ */ /* USB interface indexes (use define rather than enum to expand them) */ diff --git a/common/tpm_registers.c b/common/tpm_registers.c index 6fcd6eb839..5728dc6f92 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -570,7 +570,39 @@ static void call_extension_command(struct tpm_cmd_header *tpmh, } #endif -static void tpm_reset(void) +/* Event (to TPM task) to request reset, or (from TPM task) on completion. */ +#define TPM_EVENT_RESET (TASK_EVENT_CUSTOM(1)) + +/* Calling task to notify when the TPM reset has completed. */ +static task_id_t waiting_for_reset +/* This must not be affected by the reset, or we'll forget who to tell. */ +__attribute__((section(".data.noreinit"))) = TASK_ID_INVALID; + +int tpm_reset(void) +{ + uint32_t evt; + + cprints(CC_TASK, "%s", __func__); + + task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0); + + if (in_interrupt_context() || + task_get_current() == TASK_ID_TPM) + return 0; /* Can't sleep. Clown'll eat me. */ + + /* Try to wait until the TPM is reset, but timeout eventually */ + waiting_for_reset = task_get_current(); + evt = task_wait_event_mask(TPM_EVENT_RESET, SECOND); + + /* Timeout is bad */ + if (evt & TASK_EVENT_TIMER) + return -1; + + /* Otherwise, good */ + return 1; +} + +static void tpm_reset_now(void) { /* This is more related to TPM task activity than TPM transactions */ cprints(CC_TASK, "%s", __func__); @@ -585,16 +617,20 @@ static void tpm_reset(void) memset(__bss_libtpm2_start, __bss_libtpm2_end - __bss_libtpm2_start, 0); /* - * TPM reset currently only clears BSS for the TPM library. It does - * not reset any initialized variables in data. So, make sure there - * aren't any. + * NOTE: Any initialized variables in this file must be placed in a + * separate section (NOT .data). If they need resetting, do so here. */ - ASSERT(__data_libtpm2_start == __data_libtpm2_end); /* Re-initialize our registers */ tpm_init(); sps_tpm_enable(); + + if (waiting_for_reset != TASK_ID_INVALID) { + /* Wake the waiting task, if any */ + task_set_event(waiting_for_reset, TPM_EVENT_RESET, 0); + waiting_for_reset = TASK_ID_INVALID; + } } void tpm_task(void) @@ -614,7 +650,7 @@ void tpm_task(void) /* Wait for the next command event */ evt = task_wait_event(-1); if (evt & TPM_EVENT_RESET) { - tpm_reset(); + tpm_reset_now(); continue; } tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo; diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index 5b756cec58..9e791f0380 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -300,7 +300,15 @@ SECTIONS STRINGIFY(OUTDIR/common/tpm_registers.o*)(.data) __data_libtpm2_end = .; - *(.data) + /* + * TPM reset currently only clears BSS for the TPM library. It does + * not reset any initialized variables in data. So, make sure there + * aren't any. + */ + ASSERT(__data_libtpm2_start == __data_libtpm2_end, + "libtpm2 .data section is nonzero"); + + *(.data*) #ifdef CONFIG_MPU /* It has to be aligned by 32 bytes to be a valid MPU region. */ . = ALIGN(32); diff --git a/include/tpm_registers.h b/include/tpm_registers.h index 35f6dff471..037fc73441 100644 --- a/include/tpm_registers.h +++ b/include/tpm_registers.h @@ -32,6 +32,17 @@ void sps_tpm_disable(void); size_t tpm_get_burst_size(void); /* + * Reset the TPM. This sends a request to the TPM task, so that the reset can + * happen when the TPM task finishes whatever it's doing at the moment. + * + * Returns 0 if the request was made, but we can't wait for it to complete + * because we're in interrupt context or something similar. Otherwise, it + * blocks and returns 1 after the TPM has been cleared, or returns -1 if the + * request timed out. + */ +int tpm_reset(void); + +/* * This structure describes the header of all commands and responses sent and * received over TPM FIFO. * |