summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/tpm_lite/tlcl.h12
-rw-r--r--src/lib/tpm2_marshaling.c35
-rw-r--r--src/lib/tpm2_tlcl.c19
-rw-r--r--src/lib/tpm2_tlcl_structures.h9
4 files changed, 65 insertions, 10 deletions
diff --git a/src/include/tpm_lite/tlcl.h b/src/include/tpm_lite/tlcl.h
index c8e68d28e9..8dd5d80685 100644
--- a/src/include/tpm_lite/tlcl.h
+++ b/src/include/tpm_lite/tlcl.h
@@ -162,4 +162,16 @@ uint32_t tlcl_disable_platform_hierarchy(void);
*/
uint32_t tlcl_cr50_enable_nvcommits(void);
+/**
+ * CR50 specific tpm command to restore header(s) of the dormant RO/RW
+ * image(s) and in case there indeed was a dormant image, trigger reboot after
+ * the timeout milliseconds. Note that timeout of zero means "NO REBOOT", not
+ * "IMMEDIATE REBOOT".
+ *
+ * Return value indicates success or failure of accessing the TPM; in case of
+ * success the number of restored headers is saved in num_restored_headers.
+ */
+uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
+ uint8_t *num_restored_headers);
+
#endif /* TPM_LITE_TLCL_H_ */
diff --git a/src/lib/tpm2_marshaling.c b/src/lib/tpm2_marshaling.c
index 6d4d622d91..52dac9c553 100644
--- a/src/lib/tpm2_marshaling.c
+++ b/src/lib/tpm2_marshaling.c
@@ -394,20 +394,16 @@ 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;
+ case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON:
+ marshal_u16(buffer, sub_command[0], buffer_space);
+ marshal_u16(buffer, sub_command[1], buffer_space);
+ break;
default:
/* Unsupported subcommand. */
printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n",
@@ -596,6 +592,25 @@ static void unmarshal_nv_read(void **buffer, int *size,
*size = 0;
}
+static void unmarshal_vendor_command(void **buffer, int *size,
+ struct vendor_command_response *vcr)
+{
+ vcr->vc_subcommand = unmarshal_u16(buffer, size);
+
+ switch (vcr->vc_subcommand) {
+ case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS:
+ break;
+ case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON:
+ vcr->num_restored_headers = unmarshal_u8(buffer, size);
+ break;
+ default:
+ printk(BIOS_ERR,
+ "%s:%d - unsupported vendor command %#04x!\n",
+ __func__, __LINE__, vcr->vc_subcommand);
+ break;
+ }
+}
+
struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
void *response_body,
size_t in_size)
@@ -648,8 +663,8 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
break;
case TPM2_CR50_VENDOR_COMMAND:
- /* Assume no other data returned for the time being. */
- cr_size = 0;
+ unmarshal_vendor_command(&response_body, &cr_size,
+ &tpm2_resp->vcr);
break;
default:
diff --git a/src/lib/tpm2_tlcl.c b/src/lib/tpm2_tlcl.c
index 967612ad20..1118afb1df 100644
--- a/src/lib/tpm2_tlcl.c
+++ b/src/lib/tpm2_tlcl.c
@@ -406,3 +406,22 @@ uint32_t tlcl_cr50_enable_nvcommits(void)
}
return TPM_SUCCESS;
}
+
+uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
+ uint8_t *num_restored_headers)
+{
+ struct tpm2_response *response;
+ uint16_t command_body[] = {
+ TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms
+ };
+
+ printk(BIOS_INFO, "Checking cr50 for pending updates\n");
+
+ response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
+
+ if (!response || response->hdr.tpm_code)
+ return TPM_E_INTERNAL_INCONSISTENCY;
+
+ *num_restored_headers = response->vcr.num_restored_headers;
+ return TPM_SUCCESS;
+}
diff --git a/src/lib/tpm2_tlcl_structures.h b/src/lib/tpm2_tlcl_structures.h
index ec5b674701..2d6164b1b7 100644
--- a/src/lib/tpm2_tlcl_structures.h
+++ b/src/lib/tpm2_tlcl_structures.h
@@ -78,6 +78,7 @@ struct tpm_header {
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)
+#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24)
/* Startup values. */
#define TPM_SU_CLEAR 0
@@ -279,6 +280,13 @@ struct nv_read_response {
TPM2B_MAX_NV_BUFFER buffer;
};
+struct vendor_command_response {
+ uint16_t vc_subcommand;
+ union {
+ uint8_t num_restored_headers;
+ };
+};
+
struct tpm2_session_attrs {
uint8_t continueSession : 1;
uint8_t auditExclusive : 1;
@@ -311,6 +319,7 @@ struct tpm2_response {
struct get_cap_response gc;
struct nv_read_response nvr;
struct tpm2_session_header def_space;
+ struct vendor_command_response vcr;
};
};