• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
tlcl_cr50_enable_nvcommits(void)12 tpm_result_t tlcl_cr50_enable_nvcommits(void)
13 {
14 	uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
15 	struct tpm2_response *response;
16 
17 	printk(BIOS_INFO, "Enabling GSC nvmem commits\n");
18 
19 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
20 
21 	if (!response || (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_IOERROR;
28 	}
29 	return TPM_SUCCESS;
30 }
31 
tlcl_cr50_enable_update(uint16_t timeout_ms,uint8_t * num_restored_headers)32 tpm_result_t tlcl_cr50_enable_update(uint16_t timeout_ms,
33 				     uint8_t *num_restored_headers)
34 {
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 GSC for pending updates\n");
41 
42 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
43 
44 	if (!response || response->hdr.tpm_code)
45 		return TPM_IOERROR;
46 
47 	*num_restored_headers = response->vcr.num_restored_headers;
48 	return TPM_SUCCESS;
49 }
50 
tlcl_cr50_get_recovery_button(uint8_t * recovery_button_state)51 tpm_result_t tlcl_cr50_get_recovery_button(uint8_t *recovery_button_state)
52 {
53 	struct tpm2_response *response;
54 	uint16_t sub_command = TPM2_CR50_SUB_CMD_GET_REC_BTN;
55 
56 	printk(BIOS_INFO, "Checking GSC for recovery request\n");
57 
58 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
59 
60 	if (!response || response->hdr.tpm_code)
61 		return TPM_IOERROR;
62 
63 	*recovery_button_state = response->vcr.recovery_button_state;
64 	return TPM_SUCCESS;
65 }
66 
tlcl_cr50_get_tpm_mode(uint8_t * tpm_mode)67 tpm_result_t tlcl_cr50_get_tpm_mode(uint8_t *tpm_mode)
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 GSC TPM mode\n");
74 
75 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &mode_command);
76 
77 	if (!response)
78 		return TPM_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_CB_MUST_REBOOT;
87 	}
88 
89 	if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
90 	    response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND) {
91 		/*
92 		 * Explicitly inform caller when command is not supported
93 		 */
94 		return TPM_CB_NO_SUCH_COMMAND;
95 	}
96 
97 	if (response->hdr.tpm_code) {
98 		/* Unexpected return code from Cr50 */
99 		return TPM_IOERROR;
100 	}
101 
102 	/* TPM command completed without error */
103 	*tpm_mode = response->vcr.tpm_mode;
104 
105 	return TPM_SUCCESS;
106 }
107 
tlcl_cr50_get_boot_mode(uint8_t * boot_mode)108 tpm_result_t tlcl_cr50_get_boot_mode(uint8_t *boot_mode)
109 {
110 	struct tpm2_response *response;
111 	uint16_t mode_command = TPM2_CR50_SUB_CMD_GET_BOOT_MODE;
112 
113 	printk(BIOS_DEBUG, "Reading GSC boot mode\n");
114 
115 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &mode_command);
116 
117 	if (!response)
118 		return TPM_IOERROR;
119 
120 	if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
121 	    response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
122 		/* Explicitly inform caller when command is not supported */
123 		return TPM_CB_NO_SUCH_COMMAND;
124 
125 	if (response->hdr.tpm_code)
126 		/* Unexpected return code from Cr50 */
127 		return TPM_IOERROR;
128 
129 	*boot_mode = response->vcr.boot_mode;
130 
131 	return TPM_SUCCESS;
132 }
133 
tlcl_cr50_immediate_reset(uint16_t timeout_ms)134 tpm_result_t tlcl_cr50_immediate_reset(uint16_t timeout_ms)
135 {
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 GSC reset\n");
144 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &reset_command_body);
145 
146 	if (!response)
147 		return TPM_IOERROR;
148 
149 	return TPM_SUCCESS;
150 }
151 
tlcl_cr50_reset_ec(void)152 tpm_result_t tlcl_cr50_reset_ec(void)
153 {
154 	struct tpm2_response *response;
155 	uint16_t reset_cmd = TPM2_CR50_SUB_CMD_RESET_EC;
156 
157 	printk(BIOS_DEBUG, "Issuing EC reset\n");
158 
159 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &reset_cmd);
160 
161 	if (!response)
162 		return TPM_IOERROR;
163 
164 	if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
165 	    response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
166 		/* Explicitly inform caller when command is not supported */
167 		return TPM_CB_NO_SUCH_COMMAND;
168 
169 	if (response->hdr.tpm_code)
170 		/* Unexpected return code from Cr50 */
171 		return TPM_IOERROR;
172 
173 	printk(BIOS_DEBUG, "EC reset coming up...\n");
174 	halt();
175 
176 	return TPM_SUCCESS;
177 }
178 
tlcl_cr50_get_factory_config(uint64_t * factory_config)179 tpm_result_t tlcl_cr50_get_factory_config(uint64_t *factory_config)
180 {
181 	struct tpm2_response *response;
182 	uint16_t factory_config_command = TPM2_CR50_SUB_CMD_GET_FACTORY_CONFIG;
183 	*factory_config = 0;
184 
185 	response = tlcl2_process_command(TPM2_CR50_VENDOR_COMMAND, &factory_config_command);
186 
187 	if (!response)
188 		return TPM_IOERROR;
189 
190 	/* Explicitly inform caller when command is not supported */
191 	if (response->hdr.tpm_code == VENDOR_RC_NO_SUCH_COMMAND ||
192 	    response->hdr.tpm_code == VENDOR_RC_NO_SUCH_SUBCOMMAND)
193 		return TPM_CB_NO_SUCH_COMMAND;
194 
195 	/* Unexpected return code from TPM */
196 	if (response->hdr.tpm_code)
197 		return TPM_IOERROR;
198 
199 	/* TPM command completed without error */
200 	*factory_config = response->vcr.factory_config;
201 
202 	printk(BIOS_INFO, "Reading factory config = %016" PRIX64 "\n", *factory_config);
203 
204 	return TPM_SUCCESS;
205 }
206