diff options
-rw-r--r-- | src/include/tpm_lite/tlcl.h | 12 | ||||
-rw-r--r-- | src/lib/tpm2_marshaling.c | 35 | ||||
-rw-r--r-- | src/lib/tpm2_tlcl.c | 19 | ||||
-rw-r--r-- | src/lib/tpm2_tlcl_structures.h | 9 |
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; }; }; |