From dfced0c19148edcd1b57662ebccc2bb611383c92 Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Thu, 12 Jan 2017 21:23:24 -0800 Subject: cr50: reinstate nvmem commits 3 s after tpm reset Relying on the AP sending a PCR read as an indication of the completed boot process does not work on the resume path. Let's just enable commits 3 s after they were stopped to process tpm reset. BRANCH=none BUG=chrome-os-partner:61795 TEST=observed the following on the cr50 console on a reef during reboot: [0.018692 tpm_init] tpm_manufactured: manufactured [0.021180 tpm_reset_now: done] . . [1.166496 Skipping commit] [1.425888 Skipping commit] [1.439112 Skipping commit] . . [3.021892 Committing NVMEM changes.] and verified that reef booted normally. Change-Id: I5f64fe24b961a9d0366f8e4f40a0e44d4e7263fa Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/427328 Reviewed-by: Aaron Durbin --- common/tpm_registers.c | 51 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/common/tpm_registers.c b/common/tpm_registers.c index 9c5bb4a3b0..e60c577804 100644 --- a/common/tpm_registers.c +++ b/common/tpm_registers.c @@ -641,6 +641,7 @@ static void call_extension_command(struct tpm_cmd_header *tpmh, /* Event (to TPM task) to request reset, or (from TPM task) on completion. */ #define TPM_EVENT_RESET TASK_EVENT_CUSTOM(1 << 0) +#define TPM_EVENT_COMMIT TASK_EVENT_CUSTOM(1 << 1) /* Calling task (singular) to notify when the TPM reset has completed */ static __initialized task_id_t waiting_for_reset = TASK_ID_INVALID; @@ -696,6 +697,20 @@ int tpm_is_resetting(void) return reset_in_progress; } +/* + * A timeout hook to reinstate NVMEM commits soon after reset. + * + * The TPM task disables nvmem commits during TPM reset, they need to be + * reinstated on the same task context. This is why an event is raised here to + * wake up the TPM task and force it to reinstate nvmem commits instead of + * doing it here directly. + */ +static void reinstate_nvmem_commits(void) +{ + task_set_event(TASK_ID_TPM, TPM_EVENT_COMMIT, 0); +} +DECLARE_DEFERRED(reinstate_nvmem_commits); + static void tpm_reset_now(int wipe_first) { /* This is more related to TPM task activity than TPM transactions */ @@ -755,6 +770,13 @@ static void tpm_reset_now(int wipe_first) } cprints(CC_TASK, "%s: done", __func__); + + /* + * The host might decide to do it sooner, but let's make sure commits + * do not stay disabled for more than 3 seconds. + */ + hook_call_deferred(&reinstate_nvmem_commits_data, 3 * SECOND); + reset_in_progress = 0; } @@ -772,8 +794,23 @@ void tpm_task(void) evt = task_wait_event(-1); if (evt & TPM_EVENT_RESET) { tpm_reset_now(wipe_requested); + /* + * There is no point in looking at other events in + * this situation: the nvram will be committed by TPM + * reset; other tpm commands would be ignored. + * + * Let's just continue. This could change if there are + * other events added to the set. + */ continue; } + + if (evt & TPM_EVENT_COMMIT) + nvmem_enable_commits(); + + if (!(evt & TASK_EVENT_WAKE)) + continue; + tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo; command_code = be32toh(tpmh->command_code); CPRINTF("%s: received fifo command 0x%04x\n", @@ -801,20 +838,8 @@ void tpm_task(void) * TODO(vbendeb): revisit this when * crosbug.com/p/55667 has been addressed. */ - if (command_code == TPM2_PCR_Read) { + if (command_code == TPM2_PCR_Read) system_process_retry_counter(); - /* - * The AP issuing a PCR Read command is - * considered an indication of the boot - * process being finished. - * - * There is no need to speed up TPM operations - * any more, pending NVMEM changes should be - * committed and future NVMEM commits should - * not be postponed. - */ - nvmem_enable_commits(); - } #ifdef CONFIG_EXTENSION_COMMAND if (!IS_CUSTOM_CODE(command_code)) #endif -- cgit v1.2.1