summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-01-12 21:23:24 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-01-14 03:25:24 -0800
commitdfced0c19148edcd1b57662ebccc2bb611383c92 (patch)
tree41d9a85fda15831470b38595e8c2b9b91a6cf85a
parent71ddb610c29211230cdc7e3649f4e15e1a566028 (diff)
downloadchrome-ec-dfced0c19148edcd1b57662ebccc2bb611383c92.tar.gz
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 <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/427328 Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r--common/tpm_registers.c51
1 files 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