diff options
-rw-r--r-- | board/cr50/board.c | 4 | ||||
-rw-r--r-- | board/cr50/board.h | 3 | ||||
-rw-r--r-- | board/cr50/build.mk | 2 | ||||
-rw-r--r-- | chip/g/sps_tpm.c | 9 | ||||
-rw-r--r-- | common/tpm_registers.c | 38 | ||||
-rw-r--r-- | core/cortex-m/ec.lds.S | 16 | ||||
-rw-r--r-- | include/link_defs.h | 6 | ||||
-rw-r--r-- | include/tpm_registers.h | 2 |
8 files changed, 76 insertions, 4 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index 3f365350da..31a8d2fef1 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -394,8 +394,8 @@ void sys_rst_asserted(enum gpio_signal signal) if (usb_spi_update_in_progress() || is_sys_rst_asserted()) return; - cflush(); - system_reset(0); + /* Re-initialize the TPM software state */ + task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0); } void assert_sys_rst(void) diff --git a/board/cr50/board.h b/board/cr50/board.h index 7d11abd60d..cc7589e750 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -136,6 +136,9 @@ 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/board/cr50/build.mk b/board/cr50/build.mk index f7cc0370b6..6028e34de2 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -79,6 +79,6 @@ $(out)/RW/ec.RW.elf $(out)/RW/ec.RW_B.elf: $(out)/tpm2/libtpm2.a # Force the external build each time, so it can look for changed sources. .PHONY: $(out)/tpm2/libtpm2.a $(out)/tpm2/libtpm2.a: - $(MAKE) obj=$(realpath $(out))/tpm2 EMBEDDED_MODE=1 -C $(EXTLIB) + $(MAKE) obj=$(realpath $(out))/tpm2 EMBEDDED_MODE=1 OBJ_PREFIX=Tpm2_ -C $(EXTLIB) endif # BOARD_MK_INCLUDED_ONCE is nonempty diff --git a/chip/g/sps_tpm.c b/chip/g/sps_tpm.c index 2c3f6876e7..3ef12994e6 100644 --- a/chip/g/sps_tpm.c +++ b/chip/g/sps_tpm.c @@ -271,3 +271,12 @@ void sps_tpm_enable(void) sps_register_rx_handler(SPS_GENERIC_MODE, tpm_rx_handler, 3); init_new_cycle(); } + +void sps_tpm_disable(void) +{ + sps_tpm_state = SPS_TPM_STATE_PONDERING; + sps_unregister_rx_handler(); + /* We don't care anymore, so we can sleep whenever */ + delay_sleep_by(0); + enable_sleep(SLEEP_MASK_SPI); +} diff --git a/common/tpm_registers.c b/common/tpm_registers.c index 2f656096aa..6fcd6eb839 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -12,6 +12,7 @@ #include "byteorder.h" #include "console.h" #include "extension.h" +#include "link_defs.h" #include "nvmem.h" #include "printf.h" #include "signed_header.h" @@ -493,6 +494,9 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size) static void tpm_init(void) { + /* This is more related to TPM task activity than TPM transactions */ + cprints(CC_TASK, "%s", __func__); + set_tpm_state(tpm_state_idle); tpm_.regs.access = tpm_reg_valid_sts; /* @@ -566,6 +570,33 @@ static void call_extension_command(struct tpm_cmd_header *tpmh, } #endif +static void tpm_reset(void) +{ + /* This is more related to TPM task activity than TPM transactions */ + cprints(CC_TASK, "%s", __func__); + + sps_tpm_disable(); + + /* + * Clear the TPM library's zero-init data. Note that the linker script + * includes this file's .bss in the same section, so it will be cleared + * at the same time. + */ + 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. + */ + ASSERT(__data_libtpm2_start == __data_libtpm2_end); + + /* Re-initialize our registers */ + tpm_init(); + + sps_tpm_enable(); +} + void tpm_task(void) { if (system_rolling_reboot_suspected()) @@ -578,9 +609,14 @@ void tpm_task(void) unsigned response_size; uint32_t command_code; struct tpm_cmd_header *tpmh; + uint32_t evt; /* Wait for the next command event */ - task_wait_event(-1); + evt = task_wait_event(-1); + if (evt & TPM_EVENT_RESET) { + tpm_reset(); + continue; + } tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo; command_code = be32toh(tpmh->command_code); CPRINTF("%s: received fifo command 0x%04x\n", diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index 2b70535fa6..5b756cec58 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -243,6 +243,14 @@ SECTIONS . = ALIGN(8); *(.bss.system_stack) /* Rest of .bss takes care of its own alignment */ + + /* Group libtpm2 data so it can be cleared on system reset */ + __bss_libtpm2_start = .; + Tpm2_*(.bss) + /* TPM registers should be cleared at the same time */ + STRINGIFY(OUTDIR/common/tpm_registers.o*)(.bss) + __bss_libtpm2_end = .; + *(.bss) /* @@ -284,6 +292,14 @@ SECTIONS . = ALIGN(4); __data_start = .; *(.data.tasks) + + /* Group libtpm2 data so it can be reinitialized on system reset */ + __data_libtpm2_start = .; + Tpm2_*(.data) + /* TPM registers should be reinitialized at the same time */ + STRINGIFY(OUTDIR/common/tpm_registers.o*)(.data) + __data_libtpm2_end = .; + *(.data) #ifdef CONFIG_MPU /* It has to be aligned by 32 bytes to be a valid MPU region. */ diff --git a/include/link_defs.h b/include/link_defs.h index 69b964d1d8..e55da8bd50 100644 --- a/include/link_defs.h +++ b/include/link_defs.h @@ -87,6 +87,12 @@ extern const void *__irqhandler[]; /* Shared memory buffer. Use via shared_mem.h interface. */ extern uint8_t __shared_mem_buf[]; +/* Image sections used by the TPM2 library */ +extern uint8_t *__bss_libtpm2_start; +extern uint8_t *__bss_libtpm2_end; +extern uint8_t *__data_libtpm2_start; +extern uint8_t *__data_libtpm2_end; + /* Image sections. */ extern const void *__ro_end; extern const void *__data_start; diff --git a/include/tpm_registers.h b/include/tpm_registers.h index 3416492f03..35f6dff471 100644 --- a/include/tpm_registers.h +++ b/include/tpm_registers.h @@ -25,6 +25,8 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size); /* Enable SPS TPM driver. */ void sps_tpm_enable(void); +/* Disable SPS TPM driver. */ +void sps_tpm_disable(void); /* Get the current value of the burst size field of the status register. */ size_t tpm_get_burst_size(void); |