diff options
author | Namyoon Woo <namyoon@google.com> | 2020-05-13 19:09:35 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-06-01 17:49:45 +0000 |
commit | 77f11cd9e99bc1d6a63acee45a3d457b7f205523 (patch) | |
tree | 801ab6fb0ad27213797a09026645d62d8c3708d4 | |
parent | 5a60b3b215125e8d2c145e17867fcfaaae682dcd (diff) | |
download | chrome-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.c | 30 | ||||
-rw-r--r-- | board/cr50/board.h | 22 | ||||
-rw-r--r-- | chip/g/init_chip.h | 1 | ||||
-rw-r--r-- | common/i2cs_tpm.c | 1 | ||||
-rw-r--r-- | common/tpm_registers.c | 25 | ||||
-rw-r--r-- | include/tpm_registers.h | 3 |
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 |