summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-06-13 16:08:34 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-16 21:10:54 -0700
commit12fd77967f9239f462bb66087cf4496f36e16302 (patch)
treee0970da15c8e86c26478b8ff98deb3d48efbf204
parent3bb2d756e579be92a87ff6a17f26f78af3350e4b (diff)
downloadchrome-ec-12fd77967f9239f462bb66087cf4496f36e16302.tar.gz
cr50: handle board ID mismatch gracefully
If Cr50 happens to start on a chip where Board ID programmed in INFO1 does not match the contents of the RW header, it means that for some reason the other RW is not operational and the current image is the only viable one. In this case the Cr50 starts but operates in limited mode (only commands for updating the image and reporting state are handled). In this case the reason for recovery could be seen on the Recovery screen, and the update could be done once Chrome OS boots in recovery mode. BRANCH=none BUG=b:35586335 TEST=verified the following: - if an image with wrong board ID is started, it tries to fall back (sets the counter to a value above threshold and reboots) - if the fallback fails, the image keeps running in the limited capabilities mode but the update is possible, observed that the new image took over worked after powercycling the device. - observed proper error message on the recovery screen showing where the error comes from Change-Id: I46ba75392f8e891bb8503fb15aea2c56b5805e83 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/535978 Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r--board/cr50/board.c5
-rw-r--r--board/cr50/tpm2/tpm_state.c6
-rw-r--r--common/extension.c16
-rw-r--r--common/tpm_registers.c22
4 files changed, 45 insertions, 4 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index c36e4e9c9d..4097833662 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -639,6 +639,11 @@ static void board_init(void)
/* Indication that firmware is running, for debug purposes. */
GREG32(PMU, PWRDN_SCRATCH16) = 0xCAFECAFE;
+ /*
+ * Call the function twice to make it hardde to glitch execution into
+ * passing the check when not supposed to.
+ */
+ check_board_id_mismatch();
check_board_id_mismatch();
/* Enable battery cutoff software support on detachable devices. */
diff --git a/board/cr50/tpm2/tpm_state.c b/board/cr50/tpm2/tpm_state.c
index a9b9fdd8f8..43b28ea7b2 100644
--- a/board/cr50/tpm2/tpm_state.c
+++ b/board/cr50/tpm2/tpm_state.c
@@ -52,6 +52,12 @@ static enum vendor_cmd_rc report_tpm_state(enum vendor_cmd_cc code,
memset(state, 0, sizeof(*state));
+ if (board_id_is_mismatched()) {
+ s_failCode = 0xbadc0de;
+ s_failLine = __LINE__;
+ memcpy(&s_failFunction, __func__, sizeof(s_failFunction));
+ }
+
serialize_u32(&state->version, TPM_STATE_VERSION);
serialize_u32(&state->fail_code, s_failCode);
serialize_u32(&state->fail_line, s_failLine);
diff --git a/common/extension.c b/common/extension.c
index 0e9ad5bfca..63d20de365 100644
--- a/common/extension.c
+++ b/common/extension.c
@@ -22,6 +22,22 @@ static uint32_t extension_route_command(uint16_t command_code,
cmd_p = (struct extension_command *)&__extension_cmds;
end_p = (struct extension_command *)&__extension_cmds_end;
+#ifdef CONFIG_BOARD_ID_SUPPORT
+ if (board_id_is_mismatched()) {
+ switch (command_code) {
+ case EXTENSION_FW_UPGRADE:
+ case VENDOR_CC_REPORT_TPM_STATE:
+ case VENDOR_CC_TURN_UPDATE_ON:
+ case EXTENSION_POST_RESET:
+ break;
+ default:
+ CPRINTF("%s: ignoring command 0x%x "
+ "due to board ID mismatch\n",
+ __func__, command_code);
+ return VENDOR_RC_NO_SUCH_COMMAND;
+ }
+ }
+#endif
while (cmd_p != end_p) {
if (cmd_p->command_code == command_code)
return cmd_p->handler(command_code, buffer,
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index c4353dd566..7d4ecccfbf 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -850,10 +850,24 @@ void tpm_task(void)
} else
#endif
{
- ExecuteCommand(tpm_.fifo_write_index,
- tpm_.regs.data_fifo,
- &response_size,
- &response);
+ if (board_id_is_mismatched()) {
+ static const char tpm_broken_response[] = {
+ 0x80, 0x01, /* TPM_ST_NO_SESSIONS */
+ 0, 0, 0, 10, /* Response size. */
+ 0, 0, 9, 0x21 /* TPM_RC_LOCKOUT */
+ };
+ CPRINTF("%s: Ignoring TPM commands\n",
+ __func__);
+ response = tpm_.regs.data_fifo;
+ response_size = sizeof(tpm_broken_response);
+ memcpy(response, tpm_broken_response,
+ response_size);
+ } else {
+ ExecuteCommand(tpm_.fifo_write_index,
+ tpm_.regs.data_fifo,
+ &response_size,
+ &response);
+ }
}
CPRINTF("got %d bytes in response\n", response_size);
if (response_size &&