coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
cr50.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 
3 #include <console/console.h>
4 #include <endian.h>
5 #include <halt.h>
6 #include <vb2_api.h>
7 #include <security/tpm/tis.h>
8 #include <security/tpm/tss.h>
9 
10 #include "../../tcg-2.0/tss_marshaling.h"
11 
13 {
15  struct tpm2_response *response;
16 
17  printk(BIOS_INFO, "Enabling cr50 nvmem commits\n");
18 
19  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
20 
21  if (response == NULL || (response && response->hdr.tpm_code)) {
22  if (response)
23  printk(BIOS_INFO, "%s: failed %x\n", __func__,
24  response->hdr.tpm_code);
25  else
26  printk(BIOS_INFO, "%s: failed\n", __func__);
27  return TPM_E_IOERROR;
28  }
29  return TPM_SUCCESS;
30 }
31 
33  uint8_t *num_restored_headers)
34 {
35  struct tpm2_response *response;
36  uint16_t command_body[] = {
38  };
39 
40  printk(BIOS_INFO, "Checking cr50 for pending updates\n");
41 
42  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
43 
44  if (!response || response->hdr.tpm_code)
45  return TPM_E_IOERROR;
46 
47  *num_restored_headers = response->vcr.num_restored_headers;
48  return TPM_SUCCESS;
49 }
50 
52 {
53  struct tpm2_response *response;
55 
56  printk(BIOS_INFO, "Checking cr50 for recovery request\n");
57 
58  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
59 
60  if (!response || response->hdr.tpm_code)
61  return TPM_E_IOERROR;
62 
63  *recovery_button_state = response->vcr.recovery_button_state;
64  return TPM_SUCCESS;
65 }
66 
68 {
69  struct tpm2_response *response;
70  uint16_t mode_command = TPM2_CR50_SUB_CMD_TPM_MODE;
71  *tpm_mode = TPM_MODE_INVALID;
72 
73  printk(BIOS_INFO, "Reading cr50 TPM mode\n");
74 
75  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &mode_command);
76 
77  if (!response)
78  return TPM_E_IOERROR;
79 
80  if (response->hdr.tpm_code == VENDOR_RC_INTERNAL_ERROR) {
81  /*
82  * The Cr50 returns VENDOR_RC_INTERNAL_ERROR iff the key ladder
83  * is disabled. The Cr50 requires a reboot to re-enable the key
84  * ladder.
85  */
86  return TPM_E_MUST_REBOOT;
87  }
88 
89  if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
91  /*
92  * Explicitly inform caller when command is not supported
93  */
94  return TPM_E_NO_SUCH_COMMAND;
95  }
96 
97  if (response->hdr.tpm_code) {
98  /* Unexpected return code from Cr50 */
99  return TPM_E_IOERROR;
100  }
101 
102  /* TPM command completed without error */
103  *tpm_mode = response->vcr.tpm_mode;
104 
105  return TPM_SUCCESS;
106 }
107 
109 {
110  struct tpm2_response *response;
112 
113  printk(BIOS_DEBUG, "Reading cr50 boot mode\n");
114 
115  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &mode_command);
116 
117  if (!response)
118  return TPM_E_IOERROR;
119 
120  if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
122  /* Explicitly inform caller when command is not supported */
123  return TPM_E_NO_SUCH_COMMAND;
124 
125  if (response->hdr.tpm_code)
126  /* Unexpected return code from Cr50 */
127  return TPM_E_IOERROR;
128 
129  *boot_mode = response->vcr.boot_mode;
130 
131  return TPM_SUCCESS;
132 }
133 
135 {
136  struct tpm2_response *response;
137  uint16_t reset_command_body[] = {
139 
140  /*
141  * Issue an immediate reset to the Cr50.
142  */
143  printk(BIOS_INFO, "Issuing cr50 reset\n");
145  &reset_command_body);
146 
147  if (!response)
148  return TPM_E_IOERROR;
149 
150  return TPM_SUCCESS;
151 }
152 
154 {
155  struct tpm2_response *response;
157 
158  printk(BIOS_DEBUG, "Issuing EC reset\n");
159 
160  response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &reset_cmd);
161 
162  if (!response)
163  return TPM_E_IOERROR;
164 
165  if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
167  /* Explicitly inform caller when command is not supported */
168  return TPM_E_NO_SUCH_COMMAND;
169 
170  if (response->hdr.tpm_code)
171  /* Unexpected return code from Cr50 */
172  return TPM_E_IOERROR;
173 
174  printk(BIOS_DEBUG, "EC reset coming up...\n");
175  halt();
176 
177  return TPM_SUCCESS;
178 }
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn halt(void)
halt the system reliably
Definition: halt.c:6
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
uint32_t tlcl_cr50_get_tpm_mode(uint8_t *tpm_mode)
CR50 specific TPM command sequence to query the current TPM mode.
Definition: cr50.c:67
uint32_t tlcl_cr50_immediate_reset(uint16_t timeout_ms)
CR50 specific TPM command sequence to trigger an immediate reset to the Cr50 device after the specifi...
Definition: cr50.c:134
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms, uint8_t *num_restored_headers)
CR50 specific tpm command to restore header(s) of the dormant RO/RW image(s) and in case there indeed...
Definition: cr50.c:32
uint32_t tlcl_cr50_reset_ec(void)
CR50 specific TPM command sequence to issue an EC reset.
Definition: cr50.c:153
uint32_t tlcl_cr50_get_recovery_button(uint8_t *recovery_button_state)
CR50 specific tpm command to get the latched state of the recovery button.
Definition: cr50.c:51
uint32_t tlcl_cr50_enable_nvcommits(void)
CR50 specific tpm command to enable nvmem commits before internal timeout expires.
Definition: cr50.c:12
uint32_t tlcl_cr50_get_boot_mode(uint8_t *boot_mode)
CR50 specific TPM command sequence to query the current boot mode.
Definition: cr50.c:108
#define TPM2_CR50_SUB_CMD_TPM_MODE
Definition: cr50.h:16
#define TPM2_CR50_SUB_CMD_GET_BOOT_MODE
Definition: cr50.h:17
#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON
Definition: cr50.h:14
#define TPM2_CR50_SUB_CMD_IMMEDIATE_RESET
Definition: cr50.h:12
#define TPM2_CR50_VENDOR_COMMAND
Definition: cr50.h:11
@ TPM_MODE_INVALID
Definition: cr50.h:41
#define TPM2_CR50_SUB_CMD_RESET_EC
Definition: cr50.h:18
#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS
Definition: cr50.h:13
#define TPM2_CR50_SUB_CMD_GET_REC_BTN
Definition: cr50.h:15
@ VENDOR_RC_INTERNAL_ERROR
Definition: cr50.h:23
@ VENDOR_RC_NO_SUCH_SUBCOMMAND
Definition: cr50.h:24
@ VENDOR_RC_NO_SUCH_COMMAND
Definition: cr50.h:25
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
unsigned char uint8_t
Definition: stdint.h:8
struct vendor_command_response vcr
struct tpm_header hdr
TPM_CC tpm_code
void * tpm_process_command(TPM_CC command, void *command_body)
Definition: tss.c:19
#define TPM_SUCCESS
Definition: tss_common.h:9
#define TPM_E_IOERROR
Definition: tss_errors.h:21
#define TPM_E_MUST_REBOOT
Definition: tss_errors.h:31
#define TPM_E_NO_SUCH_COMMAND
Definition: tss_errors.h:43