blob: 31eab2d5d48aa917b779a72f393757f51377aeb7 [file] [log] [blame]
Jacob Garberfa8f5672020-05-18 13:18:19 -06001/* SPDX-License-Identifier: BSD-3-Clause */
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +01002
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +01003#include <console/console.h>
4#include <endian.h>
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -07005#include <halt.h>
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +01006#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
Jon Murphyd7b8dc92023-09-05 11:36:43 -060012tpm_result_t tlcl_cr50_enable_nvcommits(void)
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010013{
14 uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
15 struct tpm2_response *response;
16
Elyes HAOUASdf89df72021-02-07 21:15:31 +010017 printk(BIOS_INFO, "Enabling cr50 nvmem commits\n");
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010018
19 response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
20
Elyes Haouasaebccac2022-09-13 09:56:22 +020021 if (!response || (response && response->hdr.tpm_code)) {
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010022 if (response)
Jon Murphy53fc6672023-09-26 21:05:37 -060023 printk(BIOS_INFO, "%s: failed %#x\n", __func__,
Keith Shorte0f34002019-02-05 16:15:10 -070024 response->hdr.tpm_code);
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010025 else
26 printk(BIOS_INFO, "%s: failed\n", __func__);
Jon Murphy056952e2023-09-05 10:44:09 -060027 return TPM_IOERROR;
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010028 }
29 return TPM_SUCCESS;
30}
31
Jon Murphyd7b8dc92023-09-05 11:36:43 -060032tpm_result_t tlcl_cr50_enable_update(uint16_t timeout_ms,
33 uint8_t *num_restored_headers)
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010034{
35 struct tpm2_response *response;
36 uint16_t command_body[] = {
37 TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms
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)
Jon Murphy056952e2023-09-05 10:44:09 -060045 return TPM_IOERROR;
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010046
47 *num_restored_headers = response->vcr.num_restored_headers;
48 return TPM_SUCCESS;
49}
Keith Shorte371d422019-01-11 07:52:32 -070050
Jon Murphyd7b8dc92023-09-05 11:36:43 -060051tpm_result_t tlcl_cr50_get_recovery_button(uint8_t *recovery_button_state)
Keith Shorte371d422019-01-11 07:52:32 -070052{
53 struct tpm2_response *response;
54 uint16_t sub_command = TPM2_CR50_SUB_CMD_GET_REC_BTN;
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)
Jon Murphy056952e2023-09-05 10:44:09 -060061 return TPM_IOERROR;
Keith Shorte371d422019-01-11 07:52:32 -070062
63 *recovery_button_state = response->vcr.recovery_button_state;
64 return TPM_SUCCESS;
65}
Keith Shorte0f34002019-02-05 16:15:10 -070066
Jon Murphyd7b8dc92023-09-05 11:36:43 -060067tpm_result_t tlcl_cr50_get_tpm_mode(uint8_t *tpm_mode)
Keith Shorte0f34002019-02-05 16:15:10 -070068{
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)
Jon Murphy056952e2023-09-05 10:44:09 -060078 return TPM_IOERROR;
Keith Shorte0f34002019-02-05 16:15:10 -070079
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 */
Jon Murphy056952e2023-09-05 10:44:09 -060086 return TPM_CB_MUST_REBOOT;
Keith Shorte0f34002019-02-05 16:15:10 -070087 }
88
Julius Werner71a13142020-05-06 11:11:03 -070089 if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
90 response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND) {
Keith Shorte0f34002019-02-05 16:15:10 -070091 /*
92 * Explicitly inform caller when command is not supported
93 */
Jon Murphy056952e2023-09-05 10:44:09 -060094 return TPM_CB_NO_SUCH_COMMAND;
Keith Shorte0f34002019-02-05 16:15:10 -070095 }
96
97 if (response->hdr.tpm_code) {
98 /* Unexpected return code from Cr50 */
Jon Murphy056952e2023-09-05 10:44:09 -060099 return TPM_IOERROR;
Keith Shorte0f34002019-02-05 16:15:10 -0700100 }
101
102 /* TPM command completed without error */
103 *tpm_mode = response->vcr.tpm_mode;
104
105 return TPM_SUCCESS;
106}
107
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600108tpm_result_t tlcl_cr50_get_boot_mode(uint8_t *boot_mode)
dnojiri622c6b82020-04-03 10:51:50 -0700109{
110 struct tpm2_response *response;
111 uint16_t mode_command = TPM2_CR50_SUB_CMD_GET_BOOT_MODE;
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)
Jon Murphy056952e2023-09-05 10:44:09 -0600118 return TPM_IOERROR;
dnojiri622c6b82020-04-03 10:51:50 -0700119
Julius Werner71a13142020-05-06 11:11:03 -0700120 if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
121 response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
dnojiri622c6b82020-04-03 10:51:50 -0700122 /* Explicitly inform caller when command is not supported */
Jon Murphy056952e2023-09-05 10:44:09 -0600123 return TPM_CB_NO_SUCH_COMMAND;
dnojiri622c6b82020-04-03 10:51:50 -0700124
125 if (response->hdr.tpm_code)
126 /* Unexpected return code from Cr50 */
Jon Murphy056952e2023-09-05 10:44:09 -0600127 return TPM_IOERROR;
dnojiri622c6b82020-04-03 10:51:50 -0700128
129 *boot_mode = response->vcr.boot_mode;
130
131 return TPM_SUCCESS;
132}
133
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600134tpm_result_t tlcl_cr50_immediate_reset(uint16_t timeout_ms)
Keith Shorte0f34002019-02-05 16:15:10 -0700135{
136 struct tpm2_response *response;
137 uint16_t reset_command_body[] = {
138 TPM2_CR50_SUB_CMD_IMMEDIATE_RESET, timeout_ms};
139
140 /*
141 * Issue an immediate reset to the Cr50.
142 */
143 printk(BIOS_INFO, "Issuing cr50 reset\n");
144 response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND,
145 &reset_command_body);
146
147 if (!response)
Jon Murphy056952e2023-09-05 10:44:09 -0600148 return TPM_IOERROR;
Keith Shorte0f34002019-02-05 16:15:10 -0700149
150 return TPM_SUCCESS;
151}
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -0700152
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600153tpm_result_t tlcl_cr50_reset_ec(void)
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -0700154{
155 struct tpm2_response *response;
156 uint16_t reset_cmd = TPM2_CR50_SUB_CMD_RESET_EC;
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)
Jon Murphy056952e2023-09-05 10:44:09 -0600163 return TPM_IOERROR;
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -0700164
165 if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
166 response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
167 /* Explicitly inform caller when command is not supported */
Jon Murphy056952e2023-09-05 10:44:09 -0600168 return TPM_CB_NO_SUCH_COMMAND;
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -0700169
170 if (response->hdr.tpm_code)
171 /* Unexpected return code from Cr50 */
Jon Murphy056952e2023-09-05 10:44:09 -0600172 return TPM_IOERROR;
Karthikeyan Ramasubramanianba7b90e2021-03-01 13:50:20 -0700173
174 printk(BIOS_DEBUG, "EC reset coming up...\n");
175 halt();
176
177 return TPM_SUCCESS;
178}
Subrata Banik0f90c5d2023-12-27 20:59:41 +0530179
180tpm_result_t tlcl_cr50_get_factory_config(uint64_t *factory_config)
181{
182 struct tpm2_response *response;
183 uint16_t factory_config_command = TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG;
184 *factory_config = 0;
185
186 response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &factory_config_command);
187
188 if (!response)
189 return TPM_IOERROR;
190
191 /* Explicitly inform caller when command is not supported */
192 if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
193 response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
194 return TPM_CB_NO_SUCH_COMMAND;
195
196 /* Unexpected return code from TPM */
197 if (response->hdr.tpm_code)
198 return TPM_IOERROR;
199
200 /* TPM command completed without error */
201 *factory_config = response->vcr.factory_config;
202
203 printk(BIOS_INFO, "Reading factory config = %016" PRIX64 "\n", *factory_config);
204
205 return TPM_SUCCESS;
206}