summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/board.c14
-rw-r--r--common/nvmem.c32
-rw-r--r--common/tpm_registers.c22
-rw-r--r--include/nvmem.h9
4 files changed, 72 insertions, 5 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ab3f959a62..229f4ab1f0 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -403,11 +403,17 @@ void sys_rst_asserted(enum gpio_signal signal)
return;
}
- if (reboot_request_posted)
+ if (reboot_request_posted) {
+ /*
+ * Reset TPM and wait to completion to make sure nvmem is
+ * committed before reboot.
+ */
+ tpm_reset(1, 0);
system_reset(SYSTEM_RESET_HARD); /* This will never return. */
-
- /* Re-initialize the TPM software state */
- tpm_reset(0, 0);
+ } else {
+ /* Reset TPM, no need to wait for completion. */
+ tpm_reset(0, 0);
+ }
}
void assert_sys_rst(void)
diff --git a/common/nvmem.c b/common/nvmem.c
index ffdb78bb2d..a93852191c 100644
--- a/common/nvmem.c
+++ b/common/nvmem.c
@@ -45,6 +45,9 @@ struct nvmem_cache {
struct nvmem_cache cache;
+static uint8_t commits_enabled;
+static uint8_t commits_skipped;
+
/* NvMem error state */
static int nvmem_error_state;
/* Flag to track if an Nv write/move is not completed */
@@ -375,6 +378,9 @@ int nvmem_init(void)
}
CPRINTS("Active NVram partition set to %d", nvmem_act_partition);
+ commits_enabled = 1;
+ commits_skipped = 0;
+
return EC_SUCCESS;
}
@@ -510,6 +516,26 @@ int nvmem_move(uint32_t src_offset, uint32_t dest_offset, uint32_t size,
return EC_SUCCESS;
}
+void nvmem_enable_commits(void)
+{
+ if (commits_enabled)
+ return;
+
+ commits_enabled = 1;
+ if (!commits_skipped)
+ return;
+
+ CPRINTS("Committing NVMEM changes.");
+ nvmem_commit();
+ commits_skipped = 0;
+}
+
+void nvmem_disable_commits(void)
+{
+ commits_enabled = 0;
+ commits_skipped = 0;
+}
+
int nvmem_commit(void)
{
int nvmem_offset;
@@ -517,6 +543,12 @@ int nvmem_commit(void)
uint16_t version;
struct nvmem_partition *p_part;
+ if (!commits_enabled) {
+ commits_skipped = 1;
+ CPRINTS("Skipping commit");
+ return EC_SUCCESS;
+ }
+
/* Ensure that all writes/moves prior to commit call succeeded */
if (nvmem_write_error) {
CPRINTS("NvMem: Write Error, commit abandoned");
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index 62e4414a52..9c5bb4a3b0 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -730,6 +730,14 @@ static void tpm_reset_now(int wipe_first)
* reset, this is the place to do it.
*/
+ /*
+ * If TPM was reset while commits were disabled, save whatever changes
+ * might have accumulated.
+ */
+ nvmem_enable_commits();
+
+ /* Prevent NVRAM commits until further notice. */
+ nvmem_disable_commits();
/* Re-initialize our registers */
tpm_init();
@@ -793,8 +801,20 @@ 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
diff --git a/include/nvmem.h b/include/nvmem.h
index 740c845d9d..730870345a 100644
--- a/include/nvmem.h
+++ b/include/nvmem.h
@@ -177,4 +177,13 @@ int nvmem_setup(uint8_t version);
void nvmem_compute_sha(uint8_t *p_buf, int num_bytes, uint8_t *p_sha,
int sha_len);
+/*
+ * Temporarily stopping NVMEM commits could be beneficial. One use case is
+ * when TPM operations need to be sped up.
+ *
+ * Both below functions should be called from the same task.
+ */
+void nvmem_enable_commits(void);
+void nvmem_disable_commits(void);
+
#endif /* __CROS_EC_NVMEM_UTILS_H */