From 43fa560eb5c519f1a5afabe1fb2374943fe88013 Mon Sep 17 00:00:00 2001 From: Andrey Pronin Date: Wed, 26 Jan 2022 12:47:14 -0800 Subject: cr50: preserve ordely nv spaces over TPM reset This CL in case of unorderly TPM reset that doesn't also reset GSC preserves RAM-backed values of orderly nv indices. BUG=b:201101365 TEST=1) create an orderly counter 2) increment it 3) trigger EC reset 4) verify that the counter value was preserved Cq-Depend: chromium:3417937 Change-Id: I799183ad06584055d025c2acf5f83ff2ded32d39 Signed-off-by: Andrey Pronin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3418122 Reviewed-by: Vadim Bendebury Commit-Queue: Mary Ruthven --- board/cr50/tpm_nvmem_ops.c | 12 ++++++++++++ board/cr50/tpm_nvmem_ops.h | 6 ++++++ common/tpm_registers.c | 28 ++++++++++++++++++++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/board/cr50/tpm_nvmem_ops.c b/board/cr50/tpm_nvmem_ops.c index ba295c7f4f..76f740c0ee 100644 --- a/board/cr50/tpm_nvmem_ops.c +++ b/board/cr50/tpm_nvmem_ops.c @@ -108,3 +108,15 @@ size_t read_tpm_nvmem_size(uint16_t obj_index) return size; } + +BUILD_ASSERT(TPM_ORDERLY_STATE_SIZE >= RAM_INDEX_SPACE); + +void tpm_orderly_state_capture(char copy[TPM_ORDERLY_STATE_SIZE]) +{ + NvStateCapture(copy); +} + +void tpm_orderly_state_restore(const char copy[TPM_ORDERLY_STATE_SIZE]) +{ + NvStateRestore(copy); +} diff --git a/board/cr50/tpm_nvmem_ops.h b/board/cr50/tpm_nvmem_ops.h index ef1c5a07fc..da8036b16f 100644 --- a/board/cr50/tpm_nvmem_ops.h +++ b/board/cr50/tpm_nvmem_ops.h @@ -7,6 +7,8 @@ #ifndef __EC_BOARD_CR50_TPM_NVMEM_OPS_H #define __EC_BOARD_CR50_TPM_NVMEM_OPS_H +#define TPM_ORDERLY_STATE_SIZE 512 + enum tpm_read_rv { TPM_READ_SUCCESS, TPM_READ_NOT_FOUND, @@ -46,4 +48,8 @@ enum tpm_write_rv write_tpm_nvmem_hidden(uint16_t object_index, /* return size of hidden nvmem object, 0 if not found */ size_t read_tpm_nvmem_size(uint16_t obj_index); +void tpm_orderly_state_capture(char copy[TPM_ORDERLY_STATE_SIZE]); + +void tpm_orderly_state_restore(const char copy[TPM_ORDERLY_STATE_SIZE]); + #endif /* ! __EC_BOARD_CR50_TPM_NVMEM_OPS_H */ diff --git a/common/tpm_registers.c b/common/tpm_registers.c index d0ae42e904..429e895283 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -21,6 +21,7 @@ #include "system_chip.h" #include "task.h" #include "tpm_manufacture.h" +#include "tpm_nvmem_ops.h" #include "tpm_registers.h" #include "util.h" #include "watchdog.h" @@ -850,8 +851,21 @@ void tpm_reinstate_nvmem_commits(void) task_set_event(TASK_ID_TPM, TPM_EVENT_COMMIT, 0); } -static void tpm_reset_now(int wipe_first) +/* + * Reset TPM stack state. + * Called at boot, when AP resets (TPM_RESET_EVENT) and when a TPM data wipe + * is requested. + * + * Parameters: + * wipe_first - wipe TPM nvmem as a part of reset. + * can_preserve_orderly - preserve orderly nvmem spaces over a possibly + * unorderly shutdown (unless wipe_first is requested). This is a GSC + * specific modification to TPM behavior. + */ +static void tpm_reset_now(int wipe_first, int can_preserve_orderly) { + char orderly_state_copy[TPM_ORDERLY_STATE_SIZE]; + if_stop(); /* This is more related to TPM task activity than TPM transactions */ @@ -874,6 +888,9 @@ static void tpm_reset_now(int wipe_first) */ nvmem_enable_commits(); + if (can_preserve_orderly && !wipe_first) + tpm_orderly_state_capture(orderly_state_copy); + /* * 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 @@ -889,6 +906,9 @@ static void tpm_reset_now(int wipe_first) /* Re-initialize our registers */ tpm_init(); + if (can_preserve_orderly && !wipe_first) + tpm_orderly_state_restore(orderly_state_copy); + if (waiting_for_reset != TASK_ID_INVALID) { /* Wake the waiting task, if any */ task_set_event(waiting_for_reset, TPM_EVENT_RESET, 0); @@ -908,7 +928,7 @@ static void tpm_reset_now(int wipe_first) int tpm_sync_reset(int wipe_first) { - tpm_reset_now(wipe_first); + tpm_reset_now(wipe_first, 1); return wipe_result; } @@ -957,7 +977,7 @@ void tpm_task(void *u) __func__, __LINE__, evt); } - tpm_reset_now(0); + tpm_reset_now(0, 0); while (1) { uint8_t *response = NULL; unsigned response_size; @@ -971,7 +991,7 @@ void tpm_task(void *u) evt = task_wait_event(-1); if (evt & TPM_EVENT_RESET) { - tpm_reset_now(wipe_requested); + tpm_reset_now(wipe_requested, 1); if (evt & TPM_EVENT_ALT_EXTENSION) { /* * Need to tell the waiting task that -- cgit v1.2.1