diff options
-rw-r--r-- | board/cr50/board.c | 14 | ||||
-rw-r--r-- | common/nvmem.c | 32 | ||||
-rw-r--r-- | common/tpm_registers.c | 22 | ||||
-rw-r--r-- | include/nvmem.h | 9 |
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 */ |