summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/tpm_lite/tlcl.h6
-rw-r--r--src/lib/tpm2_marshaling.c37
-rw-r--r--src/lib/tpm2_tlcl.c20
-rw-r--r--src/lib/tpm2_tlcl_structures.h9
-rw-r--r--src/vboot/secdata_tpm.c2
-rw-r--r--src/vendorcode/google/chromeos/Kconfig4
6 files changed, 78 insertions, 0 deletions
diff --git a/src/include/tpm_lite/tlcl.h b/src/include/tpm_lite/tlcl.h
index 9c277a9293..c8e68d28e9 100644
--- a/src/include/tpm_lite/tlcl.h
+++ b/src/include/tpm_lite/tlcl.h
@@ -156,4 +156,10 @@ uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags);
*/
uint32_t tlcl_disable_platform_hierarchy(void);
+/**
+ * CR50 specific tpm command to enable nvmem commits before internal timeout
+ * expires.
+ */
+uint32_t tlcl_cr50_enable_nvcommits(void);
+
#endif /* TPM_LITE_TLCL_H_ */
diff --git a/src/lib/tpm2_marshaling.c b/src/lib/tpm2_marshaling.c
index dd046d27a1..6d4d622d91 100644
--- a/src/lib/tpm2_marshaling.c
+++ b/src/lib/tpm2_marshaling.c
@@ -390,6 +390,33 @@ static void marshal_hierarchy_control(void **buffer,
marshal_u8(buffer, command_body->state, buffer_space);
}
+static void marshal_cr50_vendor_command(void **buffer, void *command_body,
+ size_t *buffer_space)
+{
+ uint16_t *sub_command;
+
+ /* Ensure at least the sub command can fit in the body and there's
+ valid pointer. Could be reading past the buffer... */
+ if (command_body == NULL || *buffer_space < sizeof(uint16_t)) {
+ *buffer_space = 0;
+ return;
+ }
+
+ sub_command = command_body;
+
+ switch (*sub_command) {
+ case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS:
+ marshal_u16(buffer, *sub_command, buffer_space);
+ break;
+ default:
+ /* Unsupported subcommand. */
+ printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n",
+ *sub_command);
+ *buffer_space = 0;
+ break;
+ }
+}
+
int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
void *buffer, size_t buffer_size)
{
@@ -444,6 +471,11 @@ int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
marshal_pcr_extend(&cmd_body, tpm_command_body, &body_size);
break;
+ case TPM2_CR50_VENDOR_COMMAND:
+ marshal_cr50_vendor_command(&cmd_body, tpm_command_body,
+ &body_size);
+ break;
+
default:
body_size = 0;
printk(BIOS_INFO, "%s:%d:Request to marshal unsupported command %#x\n",
@@ -615,6 +647,11 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
cr_size = 0;
break;
+ case TPM2_CR50_VENDOR_COMMAND:
+ /* Assume no other data returned for the time being. */
+ cr_size = 0;
+ break;
+
default:
{
int i;
diff --git a/src/lib/tpm2_tlcl.c b/src/lib/tpm2_tlcl.c
index 3d65a95e97..86cc74d425 100644
--- a/src/lib/tpm2_tlcl.c
+++ b/src/lib/tpm2_tlcl.c
@@ -385,3 +385,23 @@ uint32_t tlcl_disable_platform_hierarchy(void)
return TPM_SUCCESS;
}
+
+uint32_t tlcl_cr50_enable_nvcommits(void)
+{
+ uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
+ struct tpm2_response *response;
+
+ printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n");
+
+ response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
+
+ if (response == NULL || (response && response->hdr.tpm_code)) {
+ if (response)
+ printk(BIOS_INFO, "%s: failed %x\n", __func__,
+ response->hdr.tpm_code);
+ else
+ printk(BIOS_INFO, "%s: failed\n", __func__);
+ return TPM_E_IOERROR;
+ }
+ return TPM_SUCCESS;
+}
diff --git a/src/lib/tpm2_tlcl_structures.h b/src/lib/tpm2_tlcl_structures.h
index c5c6d87985..ec5b674701 100644
--- a/src/lib/tpm2_tlcl_structures.h
+++ b/src/lib/tpm2_tlcl_structures.h
@@ -69,6 +69,15 @@ struct tpm_header {
#define TPM2_NV_Read ((TPM_CC)0x0000014E)
#define TPM2_GetCapability ((TPM_CC)0x0000017A)
#define TPM2_PCR_Extend ((TPM_CC)0x00000182)
+/* TPM2 specifies vendor commands need to have this bit set. Vendor command
+ space is defined by the lower 16 bits. */
+#define TPM_CC_VENDOR_BIT_MASK 0x20000000
+/* FIXME: below is not enough to differentiate between vendors commands
+ of numerous devices. However, the current tpm2 APIs aren't very amenable
+ to extending generically because the marshaling code is assuming all
+ knowledge of all commands. */
+#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0))
+#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21)
/* Startup values. */
#define TPM_SU_CLEAR 0
diff --git a/src/vboot/secdata_tpm.c b/src/vboot/secdata_tpm.c
index 4c1e128797..c5d08ce27f 100644
--- a/src/vboot/secdata_tpm.c
+++ b/src/vboot/secdata_tpm.c
@@ -515,6 +515,8 @@ uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
{
+ if (IS_ENABLED(CONFIG_CR50_IMMEDIATELY_COMMIT_FW_SECDATA))
+ tlcl_cr50_enable_nvcommits();
return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
}
diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig
index 97dfc60c22..3c6237abcf 100644
--- a/src/vendorcode/google/chromeos/Kconfig
+++ b/src/vendorcode/google/chromeos/Kconfig
@@ -31,6 +31,10 @@ config CHROMEOS
if CHROMEOS
+config CR50_IMMEDIATELY_COMMIT_FW_SECDATA
+ bool
+ default y if MAINBOARD_HAS_I2C_TPM_CR50 || MAINBOARD_HAS_SPI_TPM_CR50
+
config CHROMEOS_RAMOOPS
bool "Reserve space for Chrome OS ramoops"
default y