summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@google.com>2020-05-13 19:09:35 -0700
committerCommit Bot <commit-bot@chromium.org>2020-06-01 17:49:45 +0000
commit77f11cd9e99bc1d6a63acee45a3d457b7f205523 (patch)
tree801ab6fb0ad27213797a09026645d62d8c3708d4
parent5a60b3b215125e8d2c145e17867fcfaaae682dcd (diff)
downloadchrome-ec-77f11cd9e99bc1d6a63acee45a3d457b7f205523.tar.gz
Introduce TPM_BOARD_CFG register
This patch adds the TPM vendor-defined register, TPM_BOARD_CFG, which indicates the board configuration status. This register is attributed as one-time-programmable and the value is maintained across deep sleeps. Cr50 allows a write on this register right after a cr50 reset until it receives a TPM2_PCR_Extend command. BUG=b:148691139 TEST=none Signed-off-by: Namyoon Woo <namyoon@google.com> Change-Id: I89ae5a53c15990ef78812aec5da81a59f04d7d98 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2202838 Tested-by: Namyoon Woo <namyoon@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Commit-Queue: Namyoon Woo <namyoon@chromium.org>
-rw-r--r--board/cr50/board.c30
-rw-r--r--board/cr50/board.h22
-rw-r--r--chip/g/init_chip.h1
-rw-r--r--common/i2cs_tpm.c1
-rw-r--r--common/tpm_registers.c25
-rw-r--r--include/tpm_registers.h3
6 files changed, 81 insertions, 1 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 355c92ff97..3c73181cc5 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -1779,3 +1779,33 @@ int board_nvmem_legacy_check_needed(void)
return (h->major_ <= 2) || (h->minor_ <= 18);
}
+
+/*
+ * TPM_BOARD_CFG write is allowed from TPM reset until TPM2_PCR_Extend command
+ * is requested.
+ */
+static bool board_cfg_reg_write_disabled_;
+
+void board_cfg_reg_write_disable(void)
+{
+ board_cfg_reg_write_disabled_ = true;
+}
+
+void board_cfg_reg_write(uint32_t value)
+{
+ /*
+ * If BIOS requested TPM2_PCR_Extended command already or
+ * PWRDN_SCRATCH21 is already written, then do not allow the register
+ * write but return.
+ */
+ if (GREG32(PMU, PWRDN_SCRATCH21) || board_cfg_reg_write_disabled_)
+ return;
+
+ /* Store the tpm_board_cfg in power-down scratch. */
+ GREG32(PMU, PWRDN_SCRATCH21) = value|BOARD_CFG_LOCKED_BIT;
+}
+
+uint32_t board_cfg_reg_read(void)
+{
+ return GREG32(PMU, PWRDN_SCRATCH21);
+}
diff --git a/board/cr50/board.h b/board/cr50/board.h
index ea0ac15dae..67cd0f7faf 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -407,6 +407,28 @@ void board_unwedge_i2cs(void);
int board_in_prod_mode(void);
+/* Bit masks for each bit in TPM_BOARD_CFG register */
+enum board_cfg_reg_bitmask {
+ BOARD_CFG_LOCKED_BIT = BIT(31),
+};
+
+/* Disable write on TPM_BOARD_CFG register. */
+void board_cfg_reg_write_disable(void);
+
+/*
+ * Write on TPM_BOARD_CFG register if BOARD_CFG_LOCKED_BIT is clear.
+ *
+ * @param value: value to write on TPM_BOARD_CFG
+ */
+void board_cfg_reg_write(unsigned int value);
+
+/*
+ * Read TPM_BOARD_CFG register.
+ *
+ * @param TPM_BOARD_CFG register value in uint32_t type.
+ */
+unsigned int board_cfg_reg_read(void);
+
#endif /* !__ASSEMBLER__ */
/* USB interface indexes (use define rather than enum to expand them) */
diff --git a/chip/g/init_chip.h b/chip/g/init_chip.h
index a5c08cd3d9..488bb3cc4c 100644
--- a/chip/g/init_chip.h
+++ b/chip/g/init_chip.h
@@ -24,6 +24,7 @@
* SCRATCH18 - Preserving USB_DCFG through deep sleep
* SCRATCH19 - Preserving USB data sequencing PID through deep sleep
* SCRATCH20 - Preserving EC-EFS context
+ * SCRATCH21 - Preserving TPM_BOARD_CFG register
*
* PWRDN_SCRATCH 28 - 31 - Reserved for boot rom
*/
diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c
index d76befcbee..edbe7aa967 100644
--- a/common/i2cs_tpm.c
+++ b/common/i2cs_tpm.c
@@ -77,6 +77,7 @@ static const struct i2c_tpm_reg_map i2c_to_tpm[] = {
{0xa, 4, 0x14}, /* TPM TPM_INTF_CAPABILITY */
{0xe, 1, 0xf04}, /* TPM RID */
{0xf, 0, 0xf90}, /* TPM_FW_VER */
+ {0x1c, 4, 0xfe0}, /* TPM_BOARD_CFG */
};
/* Used to track number of times i2cs hw read fifo was adjusted */
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index d2862d5814..db2cba9b88 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -85,6 +85,7 @@
#define TPM_DID_VID (0xf00)
#define TPM_RID (0xf04)
#define TPM_FW_VER (0xf90)
+#define TPM_BOARD_CFG (0xfe0)
#define GOOGLE_VID 0x1ae0
#define GOOGLE_DID 0x0028
@@ -417,6 +418,17 @@ static void fifo_reg_write(const uint8_t *data, uint32_t data_size)
tpm_.regs.sts &= ~expect;
}
+/* Collect received data and write that value on TPM_BOARD_CFG register. */
+static void board_cfg_reg_write_(const uint8_t *data, uint32_t data_size)
+{
+ uint32_t value = 0;
+
+ data_size = MIN(data_size, sizeof(value));
+ memcpy(&value, data, data_size);
+
+ board_cfg_reg_write(value);
+}
+
/* TODO: data_size is between 1 and 64, but is not trustworthy! Don't write
* past the end of any actual registers if data_size is larger than the spec
* allows. */
@@ -446,6 +458,9 @@ void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
/* Reset read byte count */
tpm_fw_ver_index = 0;
break;
+ case TPM_BOARD_CFG:
+ board_cfg_reg_write_(data, data_size);
+ break;
default:
CPRINTF("%s(0x%06x, %d bytes:", __func__, regaddr, data_size);
for (i = 0; i < data_size; i++)
@@ -539,6 +554,9 @@ void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
*dest++ = 0;
}
break;
+ case TPM_BOARD_CFG:
+ copy_bytes(dest, data_size, board_cfg_reg_read());
+ break;
default:
CPRINTS("%s(0x%06x, %d) => ??", __func__, regaddr, data_size);
return;
@@ -1033,6 +1051,13 @@ void tpm_task(void *u)
*/
if (command_code == TPM2_PCR_Read)
system_process_retry_counter();
+ else if (command_code == TPM2_PCR_Extend)
+ /*
+ * Cr50 recognizes BIOS-RO exit indirectly
+ * by this command.
+ */
+ board_cfg_reg_write_disable();
+
#ifdef CONFIG_EXTENSION_COMMAND
if (!IS_CUSTOM_CODE(command_code))
#endif
diff --git a/include/tpm_registers.h b/include/tpm_registers.h
index dcdbe41566..d02bc9e276 100644
--- a/include/tpm_registers.h
+++ b/include/tpm_registers.h
@@ -104,9 +104,10 @@ struct tpm_cmd_header {
void tpm_alt_extension(struct tpm_cmd_header *tpmh, size_t buffer_size);
/*
- * The only TPM2 command we care about on the driver level, see
+ * The only TPM2 commands we care about on the driver level, see
* crosbug.com/p/55667 for detals.
*/
+#define TPM2_PCR_Extend 0x00000182
#define TPM2_PCR_Read 0x0000017e
#define TPM2_Startup 0x00000144