xref: /aosp_15_r20/external/coreboot/src/drivers/crb/tpm.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * This is a driver for a CRB Interface.
4  *
5  * The general flow looks like this:
6  *
7  * TPM starts in IDLE Mode
8  *
9  *   IDLE  --> READY --> Command Reception
10  *    ^	                        |
11  *    |	                        v
12       -- Cmd Complete <-- Command Execution
13  */
14 
15 #include <timer.h>
16 #include <console/console.h>
17 #include <device/mmio.h>
18 #include <string.h>
19 #include <soc/pci_devs.h>
20 #include <device/pci_ops.h>
21 
22 #include "tpm.h"
23 
24 static struct control_area {
25 	uint32_t request;
26 	uint32_t status;
27 	uint32_t cancel;
28 	uint32_t start;
29 	uint64_t interrupt_control;
30 	uint32_t command_size;
31 	void *command_bfr;
32 	uint32_t response_size;
33 	void *response_bfr;
34 } control_area;
35 
36 static uint8_t cur_loc = 0;
37 
38 /* Read Control Area Structure back  */
crb_readControlArea(void)39 static void crb_readControlArea(void)
40 {
41 	control_area.request = read32(CRB_REG(cur_loc, CRB_REG_REQUEST));
42 	control_area.status = read32(CRB_REG(cur_loc, CRB_REG_STATUS));
43 	control_area.cancel = read32(CRB_REG(cur_loc, CRB_REG_CANCEL));
44 	control_area.interrupt_control = read64(CRB_REG(cur_loc, CRB_REG_INT_CTRL));
45 	control_area.command_size = read32(CRB_REG(cur_loc, CRB_REG_CMD_SIZE));
46 	control_area.command_bfr =
47 		(void *)(uintptr_t)read64(CRB_REG(cur_loc, CRB_REG_CMD_ADDR));
48 	control_area.response_size = read32(CRB_REG(cur_loc, CRB_REG_RESP_SIZE));
49 	control_area.response_bfr =
50 		(void *)(uintptr_t)read64(CRB_REG(cur_loc, CRB_REG_RESP_ADDR));
51 
52 	/*
53 	 * Intel PTT has to write the command/response address and size
54 	 * register before each command submission otherwise the control area
55 	 * is all zeroed. This has been observed on Alder Lake S CPU and may be
56 	 * applicable to other new microarchitectures. Update the local control
57 	 * area data to make crb_tpm_process_command() not fail on buffer checks.
58 	 * PTT command/response buffer is fixed to be at offset 0x80 and spans
59 	 * up to the end of 4KB region for the current locality.
60 	 */
61 	if (CONFIG(HAVE_INTEL_PTT)) {
62 		control_area.command_size = 0x1000 - CRB_REG_DATA_BUFF;
63 		control_area.response_size = control_area.command_size;
64 		control_area.command_bfr = CRB_REG(cur_loc, CRB_REG_DATA_BUFF);
65 		control_area.response_bfr = CRB_REG(cur_loc, CRB_REG_DATA_BUFF);
66 	}
67 }
68 
69 /* Wait for Reg to be expected Value  */
crb_wait_for_reg32(const void * addr,uint32_t timeoutMs,uint32_t mask,uint32_t expectedValue)70 static tpm_result_t crb_wait_for_reg32(const void *addr, uint32_t timeoutMs, uint32_t mask,
71 			      uint32_t expectedValue)
72 {
73 	uint32_t regValue;
74 	struct stopwatch sw;
75 
76 	// Set up a timer which breaks the loop after timeout
77 	stopwatch_init_msecs_expire(&sw, timeoutMs);
78 
79 	while (1) {
80 		// Now check if the TPM is in IDLE mode
81 		regValue = read32(addr);
82 
83 		if ((regValue & mask) == expectedValue)
84 			return TPM_SUCCESS;
85 
86 		if (stopwatch_expired(&sw)) {
87 			printk(BIOS_ERR,
88 			       "CRB_WAIT: Error - Timed out with RegValue: %08x, Mask: %08x, Expected: %08x\n",
89 			       regValue, mask, expectedValue);
90 			return TPM_CB_TIMEOUT;
91 		}
92 	}
93 }
94 
95 /* CRB PROBE
96  *
97  * Checks if the CRB Interface is ready
98  */
crb_probe(void)99 static tpm_result_t crb_probe(void)
100 {
101 	uint64_t tpmStatus = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID));
102 	printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus);
103 
104 	if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) {
105 		printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n");
106 		return TPM_CB_FAIL;
107 	}
108 
109 	if ((tpmStatus & (0xf)) != 1) {
110 		printk(BIOS_DEBUG,
111 		       "TPM: CRB Interface is not active. System needs reboot in order to active TPM.\n");
112 		write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL);
113 		return TPM_CB_FAIL;
114 	}
115 
116 	write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL);
117 	write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_LOCK);
118 
119 	return TPM_SUCCESS;
120 }
121 
122 /*
123  * Get active Locality
124  *
125  * Get the active locality
126  */
crb_activate_locality(void)127 static uint8_t crb_activate_locality(void)
128 {
129 	uint8_t locality = (read8(CRB_REG(0, CRB_REG_LOC_STATE)) >> 2) & 0x07;
130 	printk(BIOS_SPEW, "Active locality: %i\n", locality);
131 
132 	tpm_result_t rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750,
133 				    LOC_STATE_LOC_ASSIGN, LOC_STATE_LOC_ASSIGN);
134 
135 	if (!rc && (locality == 0))
136 		return locality;
137 
138 	if (rc)
139 		write8(CRB_REG(locality, CRB_REG_LOC_CTRL), LOC_CTRL_REQ_ACCESS);
140 
141 	rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750, LOC_STATE_LOC_ASSIGN,
142 				LOC_STATE_LOC_ASSIGN);
143 	if (rc) {
144 		printk(BIOS_ERR, "TPM: Error (%#x) - No Locality has been assigned TPM-wise.\n", rc);
145 		return 0;
146 	}
147 
148 	rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 1500,
149 				LOC_STATE_REG_VALID_STS, LOC_STATE_REG_VALID_STS);
150 	if (rc) {
151 		printk(BIOS_ERR, "TPM: Error (%#x) - LOC_STATE Register %u contains errors.\n",
152 		       rc, locality);
153 		return 0;
154 	}
155 
156 	return locality;
157 }
158 
159 /* Switch Device into a Ready State */
crb_switch_to_ready(void)160 static tpm_result_t crb_switch_to_ready(void)
161 {
162 	/* Transition into ready state */
163 	write8(CRB_REG(cur_loc, CRB_REG_REQUEST), 0x1);
164 	tpm_result_t rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_REQUEST), 200,
165 					CRB_REG_REQUEST_CMD_RDY, 0x0);
166 	if (rc) {
167 		printk(BIOS_ERR,
168 		       "TPM Error (%#x): TPM did not transition into ready state in time.\n", rc);
169 		return rc;
170 	}
171 
172 	/* Check TPM_CRB_CTRL_STS[0] to be "0" - no unrecoverable error */
173 	rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 500, CRB_REG_STATUS_ERROR,
174 				0x0);
175 	if (rc) {
176 		printk(BIOS_ERR, "TPM Error (%#x): Could not recover.\n", rc);
177 		return rc;
178 	}
179 
180 	return TPM_SUCCESS;
181 }
182 
183 /*
184  * crb_tpm_init
185  *
186  * Even though the TPM does not need an initialization we check
187  * if the TPM responds and is in IDLE mode, which should be the
188  * normal bring up mode.
189  *
190  */
crb_tpm_init(void)191 tpm_result_t crb_tpm_init(void)
192 {
193 	tpm_result_t rc = crb_probe();
194 	if (rc) {
195 		printk(BIOS_ERR, "TPM: Probe failed.\n");
196 		return rc;
197 	}
198 
199 	/* Read back control area structure */
200 	crb_readControlArea();
201 
202 	/*
203 	 * PTT may have no assigned locality before startup. Request locality here to save
204 	 * some precious milliseconds which would be wasted in crb_activate_locality polling
205 	 * for LOC_STATE_LOC_ASSIGN bit for the first time.
206 	 */
207 	if (CONFIG(HAVE_INTEL_PTT)) {
208 		uint8_t locality = (read8(CRB_REG(0, CRB_REG_LOC_STATE)) >> 2) & 0x07;
209 		write8(CRB_REG(locality, CRB_REG_LOC_CTRL), LOC_CTRL_REQ_ACCESS);
210 	}
211 
212 	/* Good to go. */
213 	printk(BIOS_SPEW, "TPM: CRB TPM initialized successfully\n");
214 
215 	return TPM_SUCCESS;
216 }
217 
set_ptt_cmd_resp_buffers(void)218 static void set_ptt_cmd_resp_buffers(void)
219 {
220 	write32(CRB_REG(cur_loc, CRB_REG_CMD_ADDR + 4), 0);
221 	write32(CRB_REG(cur_loc, CRB_REG_CMD_ADDR),
222 		(uintptr_t)CRB_REG(cur_loc, CRB_REG_DATA_BUFF));
223 	write32(CRB_REG(cur_loc, CRB_REG_CMD_SIZE), control_area.command_size);
224 	write64(CRB_REG(cur_loc, CRB_REG_RESP_ADDR),
225 		(uintptr_t)CRB_REG(cur_loc, CRB_REG_DATA_BUFF));
226 	write32(CRB_REG(cur_loc, CRB_REG_RESP_SIZE), control_area.response_size);
227 }
228 
229 /*
230  * crb_tpm_process_command
231  */
crb_tpm_process_command(const void * tpm2_command,size_t command_size,void * tpm2_response,size_t max_response)232 size_t crb_tpm_process_command(const void *tpm2_command, size_t command_size,
233 			       void *tpm2_response, size_t max_response)
234 {
235 	tpm_result_t rc;
236 
237 	if (command_size > control_area.command_size) {
238 		printk(BIOS_ERR, "TPM: Command size is too big.\n");
239 		return -1;
240 	}
241 
242 	if (control_area.response_size < max_response) {
243 		printk(BIOS_ERR, "TPM: Response size could be too big.\n");
244 		return -1;
245 	}
246 
247 	cur_loc = crb_activate_locality();
248 
249 	// Check if CMD bit is cleared.
250 	rc = crb_wait_for_reg32(CRB_REG(0, CRB_REG_START), 250, CRB_REG_START_START, 0x0);
251 	if (rc) {
252 		printk(BIOS_ERR, "TPM Error (%#x): Cmd Bit not cleared.\n", rc);
253 		return -1;
254 	}
255 
256 	rc = crb_switch_to_ready();
257 	if (rc) {
258 		printk(BIOS_DEBUG, "TPM Error (%#x): Can not transition into ready state.\n", rc);
259 		return -1;
260 	}
261 
262 	// Write to Command Buffer
263 	memcpy(control_area.command_bfr, tpm2_command, command_size);
264 
265 	/*
266 	 * Initialize CRB addresses and sizes for PTT. It seems to be possible
267 	 * only after CRB is switched to ready and before writing start bit.
268 	 * This is also what EDK2 TPM CRB drivers do.
269 	 */
270 	if (CONFIG(HAVE_INTEL_PTT))
271 		set_ptt_cmd_resp_buffers();
272 
273 	// Write Start Bit
274 	write8(CRB_REG(cur_loc, CRB_REG_START), 0x1);
275 
276 	// Poll for Response
277 	rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_START), 3500, CRB_REG_START_START, 0);
278 	if (rc) {
279 		printk(BIOS_DEBUG, "TPM Error (%#x): Command Timed out.\n", rc);
280 		return -1;
281 	}
282 
283 	// Check for errors
284 	rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 200, CRB_REG_STATUS_ERROR, 0);
285 	if (rc) {
286 		printk(BIOS_DEBUG, "TPM Error (%#x): Command errored.\n", rc);
287 		return -1;
288 	}
289 
290 	// Get Response Length
291 	uint32_t length = be32_to_cpu(read32(control_area.response_bfr + 2));
292 
293 	/* Response has to have at least 6 bytes */
294 	if (length < 6)
295 		return 1;
296 
297 	// Copy Response
298 	memcpy(tpm2_response, control_area.response_bfr, length);
299 
300 	rc = crb_switch_to_ready();
301 	if (rc) {
302 		printk(BIOS_DEBUG, "TPM Error (%#x): Can not transition into ready state again.\n", rc);
303 		return -1;
304 	}
305 
306 	return length;
307 }
308 
309 /*
310  * tp2_get_info
311  *
312  * Returns information about the TPM
313  *
314  */
crb_tpm_get_info(struct crb_tpm_info * crb_tpm_info)315 void crb_tpm_get_info(struct crb_tpm_info *crb_tpm_info)
316 {
317 	uint64_t interfaceReg = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID));
318 
319 	crb_tpm_info->vendor_id = (interfaceReg >> 48) & 0xFFFF;
320 	crb_tpm_info->device_id = (interfaceReg >> 32) & 0xFFFF;
321 	crb_tpm_info->revision = (interfaceReg >> 24) & 0xFF;
322 }
323 
324 /*
325  * crb_tpm_is_active
326  *
327  * Checks that CRB interface is available and active.
328  *
329  * The body was derived from crb_probe() which unlike this function can also
330  * write to registers.
331  */
crb_tpm_is_active(void)332 bool crb_tpm_is_active(void)
333 {
334 	uint64_t tpmStatus = read64(CRB_REG(0, CRB_REG_INTF_ID));
335 	printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus);
336 
337 	if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) {
338 		printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n");
339 		return false;
340 	}
341 
342 	if ((tpmStatus & (0xf)) != 1) {
343 		printk(BIOS_DEBUG, "TPM: CRB Interface is not active.\n");
344 		return false;
345 	}
346 
347 	return true;
348 }
349