xref: /freebsd/sys/dev/tpm/tpm_crb.c (revision 1fd43ee968c497223254038483685d9f9c68791b)
1 /*-
2  * Copyright (c) 2018 Stormshield.
3  * Copyright (c) 2018 Semihalf.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 #include "tpm20.h"
30 
31 /*
32  * CRB register space as defined in
33  * TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22
34  */
35 #define	TPM_LOC_STATE			0x0
36 #define	TPM_LOC_CTRL			0x8
37 #define	TPM_LOC_STS			0xC
38 #define	TPM_CRB_INTF_ID			0x30
39 #define	TPM_CRB_CTRL_EXT		0x38
40 #define	TPM_CRB_CTRL_REQ		0x40
41 #define	TPM_CRB_CTRL_STS		0x44
42 #define	TPM_CRB_CTRL_CANCEL		0x48
43 #define	TPM_CRB_CTRL_START		0x4C
44 #define	TPM_CRB_INT_ENABLE		0x50
45 #define	TPM_CRB_INT_STS			0x54
46 #define	TPM_CRB_CTRL_CMD_SIZE		0x58
47 #define	TPM_CRB_CTRL_CMD_LADDR		0x5C
48 #define	TPM_CRB_CTRL_CMD_HADDR		0x60
49 #define	TPM_CRB_CTRL_RSP_SIZE		0x64
50 #define	TPM_CRB_CTRL_RSP_ADDR		0x68
51 #define	TPM_CRB_CTRL_RSP_HADDR		0x6c
52 #define	TPM_CRB_DATA_BUFFER		0x80
53 
54 #define	TPM_LOC_STATE_ESTB		BIT(0)
55 #define	TPM_LOC_STATE_ASSIGNED		BIT(1)
56 #define	TPM_LOC_STATE_ACTIVE_MASK	0x9C
57 #define	TPM_LOC_STATE_VALID		BIT(7)
58 
59 #define	TPM_CRB_INTF_ID_TYPE_CRB	0x1
60 #define	TPM_CRB_INTF_ID_TYPE		0x7
61 
62 #define	TPM_LOC_CTRL_REQUEST		BIT(0)
63 #define	TPM_LOC_CTRL_RELINQUISH		BIT(1)
64 
65 #define	TPM_CRB_CTRL_REQ_GO_READY	BIT(0)
66 #define	TPM_CRB_CTRL_REQ_GO_IDLE	BIT(1)
67 
68 #define	TPM_CRB_CTRL_STS_ERR_BIT	BIT(0)
69 #define	TPM_CRB_CTRL_STS_IDLE_BIT	BIT(1)
70 
71 #define	TPM_CRB_CTRL_CANCEL_CMD		0x1
72 #define	TPM_CRB_CTRL_CANCEL_CLEAR	0x0
73 
74 #define	TPM_CRB_CTRL_START_CMD		BIT(0)
75 
76 #define	TPM_CRB_INT_ENABLE_BIT		BIT(31)
77 
78 struct tpmcrb_sc;
79 /* Attach */
80 typedef bool (sm_attach_t)(struct tpmcrb_sc *, void *, size_t);
81 /* State change notification (timeout == 0 for 'no timeout') */
82 typedef bool (sm_statechange_t)(struct tpmcrb_sc *, int);
83 
84 struct tpmcrb_sm_cfg {
85 	sm_attach_t		*sm_attach;
86 	sm_statechange_t	*sm_statechange;
87 	sm_statechange_t	*sm_cmdready;
88 };
89 
90 static sm_attach_t		pluton_attach;
91 static sm_statechange_t		pluton_doorbell;
92 
93 static const struct tpmcrb_sm_cfg_map {
94 	int				acpi_sm;
95 	const char			*desc;
96 	const struct tpmcrb_sm_cfg	sm_cfg;
97 } tpmcrb_sm_cfg_map[] = {
98 	{
99 		.acpi_sm = TPM2_START_METHOD_CRB,
100 		.desc = "Trusted Platform Module 2.0, CRB mode",
101 		.sm_cfg = { NULL },	/* No notifications required */
102 	},
103 	{
104 		.acpi_sm = ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON,
105 		.desc = "Trusted Platform Module 2.0, CRB mode (Pluton)",
106 		.sm_cfg = {
107 			.sm_attach = &pluton_attach,
108 			.sm_statechange = &pluton_doorbell,
109 			.sm_cmdready = &pluton_doorbell,
110 		},
111 	},
112 };
113 
114 struct tpmcrb_sc {
115 	struct tpm_sc	base;
116 	const struct tpmcrb_sm_cfg	*sm_cfg;
117 	union {
118 		/* StartMethod data */
119 		struct {
120 			uint64_t	 start_reg;
121 			uint64_t	 reply_reg;
122 		} pluton;
123 	};
124 	bus_size_t	cmd_off;
125 	bus_size_t	rsp_off;
126 	size_t		cmd_buf_size;
127 	size_t		rsp_buf_size;
128 };
129 
130 int tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t size);
131 
132 static int tpmcrb_acpi_probe(device_t dev);
133 static int tpmcrb_attach(device_t dev);
134 static int tpmcrb_detach(device_t dev);
135 
136 static ACPI_STATUS tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg);
137 
138 static bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off,
139     uint32_t mask, uint32_t val, int32_t timeout);
140 static bool tpmcrb_request_locality(struct tpm_sc *sc, int locality);
141 static void tpmcrb_relinquish_locality(struct tpm_sc *sc);
142 static bool tpmcrb_cancel_cmd(struct tpm_sc *sc);
143 
144 char *tpmcrb_ids[] = {"MSFT0101", NULL};
145 
146 static const struct tpmcrb_sm_cfg_map *
tpmcrb_acpi_startmethod_cfg(int method)147 tpmcrb_acpi_startmethod_cfg(int method)
148 {
149 	const struct tpmcrb_sm_cfg_map *entry;
150 
151 	for (size_t i = 0; i < nitems(tpmcrb_sm_cfg_map); i++) {
152 		entry = &tpmcrb_sm_cfg_map[i];
153 
154 		if (method == entry->acpi_sm)
155 			return (entry);
156 	}
157 
158 	return (NULL);
159 }
160 
161 static int
tpmcrb_acpi_probe(device_t dev)162 tpmcrb_acpi_probe(device_t dev)
163 {
164 	int err, smethod;
165 	const struct tpmcrb_sm_cfg_map *sm_cfg_map;
166 	ACPI_TABLE_TPM23 *tbl;
167 	ACPI_STATUS status;
168 
169 	err = ACPI_ID_PROBE(device_get_parent(dev), dev, tpmcrb_ids, NULL);
170 	if (err > 0)
171 		return (err);
172 	/*Find TPM2 Header*/
173 	status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **) &tbl);
174 	if (ACPI_FAILURE(status))
175 		return (ENXIO);
176 
177 	smethod = tbl->StartMethod;
178 	AcpiPutTable((ACPI_TABLE_HEADER *)tbl);
179 
180 	sm_cfg_map = tpmcrb_acpi_startmethod_cfg(smethod);
181 	if (sm_cfg_map == NULL)
182 		return (ENXIO);
183 
184 	device_set_desc(dev, sm_cfg_map->desc);
185 	return (0);
186 }
187 
188 static ACPI_STATUS
tpmcrb_fix_buff_offsets(ACPI_RESOURCE * res,void * arg)189 tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg)
190 {
191 	struct tpmcrb_sc *crb_sc;
192 	size_t length;
193 	uint32_t base_addr;
194 
195 	crb_sc = (struct tpmcrb_sc *)arg;
196 
197 	if (res->Type != ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
198 		return (AE_OK);
199 
200 	base_addr = res->Data.FixedMemory32.Address;
201 	length = res->Data.FixedMemory32.AddressLength;
202 
203 	if (crb_sc->cmd_off > base_addr && crb_sc->cmd_off < base_addr + length)
204 		crb_sc->cmd_off -= base_addr;
205 	if (crb_sc->rsp_off > base_addr && crb_sc->rsp_off < base_addr + length)
206 		crb_sc->rsp_off -= base_addr;
207 
208 	return (AE_OK);
209 }
210 
211 static bool
tpmcrb_attach_startmethod(struct tpmcrb_sc * crb_sc)212 tpmcrb_attach_startmethod(struct tpmcrb_sc *crb_sc)
213 {
214 	const struct tpmcrb_sm_cfg_map *sm_cfg_map;
215 	const struct tpmcrb_sm_cfg *sm_cfg;
216 	ACPI_TABLE_TPM23 *tbl;
217 	void *smdata;
218 	ACPI_STATUS status;
219 	bool ret;
220 
221 	/*
222 	 * Grab what we need from the StartMethod.
223 	 */
224 	status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **)(void **)&tbl);
225 	if (ACPI_FAILURE(status))
226 		return (false);
227 
228 	sm_cfg_map = tpmcrb_acpi_startmethod_cfg(tbl->StartMethod);
229 	MPASS(sm_cfg_map != NULL);
230 	sm_cfg = &sm_cfg_map->sm_cfg;
231 
232 	crb_sc->sm_cfg = sm_cfg;
233 	smdata = tbl + 1;
234 	if (sm_cfg->sm_attach != NULL) {
235 		ret = (*sm_cfg->sm_attach)(crb_sc, smdata,
236 		    tbl->Header.Length - sizeof(*tbl));
237 	} else {
238 		ret = true;
239 	}
240 
241 	AcpiPutTable((ACPI_TABLE_HEADER *)tbl);
242 	return (ret);
243 }
244 
245 static int
tpmcrb_attach(device_t dev)246 tpmcrb_attach(device_t dev)
247 {
248 	struct tpmcrb_sc *crb_sc;
249 	struct tpm_sc *sc;
250 	ACPI_HANDLE handle;
251 	ACPI_STATUS status;
252 	int result;
253 
254 	crb_sc = device_get_softc(dev);
255 	sc = &crb_sc->base;
256 	handle = acpi_get_handle(dev);
257 	sc->dev = dev;
258 
259 	sx_init(&sc->dev_lock, "TPM driver lock");
260 
261 	sc->mem_rid = 0;
262 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
263 					     RF_ACTIVE);
264 	if (sc->mem_res == NULL) {
265 		tpmcrb_detach(dev);
266 		return (ENXIO);
267 	}
268 
269 	if (!tpmcrb_attach_startmethod(crb_sc)) {
270 		tpmcrb_detach(dev);
271 		return (ENXIO);
272 	}
273 
274 	if(!tpmcrb_request_locality(sc, 0)) {
275 		tpmcrb_detach(dev);
276 		return (ENXIO);
277 	}
278 
279 	/*
280 	 * Disable all interrupts for now, since I don't have a device that
281 	 * works in CRB mode and supports them.
282 	 */
283 	AND4(sc, TPM_CRB_INT_ENABLE, ~TPM_CRB_INT_ENABLE_BIT);
284 	sc->interrupts = false;
285 
286 	/*
287 	 * Read addresses of Tx/Rx buffers and their sizes. Note that they
288 	 * can be implemented by a single buffer. Also for some reason CMD
289 	 * addr is stored in two 4 byte neighboring registers, whereas RSP is
290 	 * stored in a single 8 byte one.
291 	 */
292 #ifdef __amd64__
293 	crb_sc->rsp_off = TPM_READ_8(sc->dev, TPM_CRB_CTRL_RSP_ADDR);
294 #else
295 	crb_sc->rsp_off = TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_ADDR);
296 	crb_sc->rsp_off |= ((uint64_t) TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_HADDR) << 32);
297 #endif
298 	crb_sc->cmd_off = TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_LADDR);
299 	crb_sc->cmd_off |= ((uint64_t) TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_HADDR) << 32);
300 	crb_sc->cmd_buf_size = TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_SIZE);
301 	crb_sc->rsp_buf_size = TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_SIZE);
302 
303 	tpmcrb_relinquish_locality(sc);
304 
305 	/* Emulator returns address in acpi space instead of an offset */
306 	status = AcpiWalkResources(handle, "_CRS", tpmcrb_fix_buff_offsets,
307 		    (void *)crb_sc);
308 	if (ACPI_FAILURE(status)) {
309 		tpmcrb_detach(dev);
310 		return (ENXIO);
311 	}
312 
313 	if (crb_sc->rsp_off == crb_sc->cmd_off) {
314 		/*
315 		 * If Tx/Rx buffers are implemented as one they have to be of
316 		 * same size
317 		 */
318 		if (crb_sc->cmd_buf_size != crb_sc->rsp_buf_size) {
319 			device_printf(sc->dev,
320 			    "Overlapping Tx/Rx buffers have different sizes\n");
321 			tpmcrb_detach(dev);
322 			return (ENXIO);
323 		}
324 	}
325 
326 	result = tpm20_init(sc);
327 	if (result != 0)
328 		tpmcrb_detach(dev);
329 
330 	return (result);
331 }
332 
333 static int
tpmcrb_detach(device_t dev)334 tpmcrb_detach(device_t dev)
335 {
336 	struct tpm_sc *sc;
337 
338 	sc = device_get_softc(dev);
339 	tpm20_release(sc);
340 
341 	if (sc->mem_res != NULL)
342 		bus_release_resource(dev, SYS_RES_MEMORY,
343 		    sc->mem_rid, sc->mem_res);
344 
345 	return (0);
346 }
347 
348 static bool
tpm_wait_for_u32(struct tpm_sc * sc,bus_size_t off,uint32_t mask,uint32_t val,int32_t timeout)349 tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off, uint32_t mask, uint32_t val,
350     int32_t timeout)
351 {
352 
353 	/* Check for condition */
354 	if ((TPM_READ_4(sc->dev, off) & mask) == val)
355 		return (true);
356 
357 	while (timeout > 0) {
358 		if ((TPM_READ_4(sc->dev, off) & mask) == val)
359 			return (true);
360 
361 		pause("TPM in polling mode", 1);
362 		timeout -= tick;
363 	}
364 	return (false);
365 }
366 
367 static bool
tpmcrb_request_locality(struct tpm_sc * sc,int locality)368 tpmcrb_request_locality(struct tpm_sc *sc, int locality)
369 {
370 	uint32_t mask;
371 
372 	/* Currently we only support Locality 0 */
373 	if (locality != 0)
374 		return (false);
375 
376 	mask = TPM_LOC_STATE_VALID | TPM_LOC_STATE_ASSIGNED;
377 
378 	OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_REQUEST);
379 	if (!tpm_wait_for_u32(sc, TPM_LOC_STATE, mask, mask, TPM_TIMEOUT_C))
380 		return (false);
381 
382 	return (true);
383 }
384 
385 static void
tpmcrb_relinquish_locality(struct tpm_sc * sc)386 tpmcrb_relinquish_locality(struct tpm_sc *sc)
387 {
388 
389 	OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_RELINQUISH);
390 }
391 
392 static bool
tpmcrb_cancel_cmd(struct tpm_sc * sc)393 tpmcrb_cancel_cmd(struct tpm_sc *sc)
394 {
395 	uint32_t mask = ~0;
396 
397 	TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CMD);
398 	if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START,
399 		    mask, ~mask, TPM_TIMEOUT_B)) {
400 		device_printf(sc->dev,
401 		    "Device failed to cancel command\n");
402 		return (false);
403 	}
404 
405 	TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
406 	return (true);
407 }
408 
409 static bool
tpmcrb_notify_cmdready(struct tpmcrb_sc * crb_sc,int timeout)410 tpmcrb_notify_cmdready(struct tpmcrb_sc *crb_sc, int timeout)
411 {
412 	sm_statechange_t *cmdready_fn;
413 
414 	cmdready_fn = crb_sc->sm_cfg->sm_cmdready;
415 	if (cmdready_fn == NULL)
416 		return (true);
417 
418 	return ((*cmdready_fn)(crb_sc, timeout));
419 }
420 
421 static bool
tpmcrb_notify_state_changing(struct tpmcrb_sc * crb_sc,int timeout)422 tpmcrb_notify_state_changing(struct tpmcrb_sc *crb_sc, int timeout)
423 {
424 	sm_statechange_t *statechange_fn;
425 
426 	statechange_fn = crb_sc->sm_cfg->sm_statechange;
427 	if (statechange_fn == NULL)
428 		return (true);
429 
430 	return ((*statechange_fn)(crb_sc, timeout));
431 }
432 
433 static bool
tpmcrb_state_idle(struct tpmcrb_sc * crb_sc,bool wait)434 tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait)
435 {
436 	struct tpm_sc *sc;
437 	int mask, timeout;
438 
439 	timeout = wait ? TPM_TIMEOUT_C : 0;
440 
441 	sc = &crb_sc->base;
442 	OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
443 
444 	if (!tpmcrb_notify_state_changing(crb_sc, timeout))
445 		return (false);
446 
447 	if (timeout > 0) {
448 		mask = TPM_CRB_CTRL_STS_IDLE_BIT;
449 		if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, mask,
450 		    timeout))
451 			return (false);
452 	}
453 
454 	return (true);
455 }
456 
457 static bool
tpmcrb_state_ready(struct tpmcrb_sc * crb_sc,bool wait)458 tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait)
459 {
460 	struct tpm_sc *sc;
461 	int mask, timeout;
462 
463 	timeout = wait ? TPM_TIMEOUT_C : 0;
464 
465 	sc = &crb_sc->base;
466 	OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
467 
468 	if (!tpmcrb_notify_state_changing(crb_sc, timeout))
469 		return (false);
470 
471 	if (timeout > 0) {
472 		mask = TPM_CRB_CTRL_REQ_GO_READY;
473 		if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, !mask,
474 		    timeout))
475 			return (false);
476 	}
477 
478 	return (true);
479 }
480 
481 int
tpmcrb_transmit(device_t dev,struct tpm_priv * priv,size_t length)482 tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length)
483 {
484 	struct tpmcrb_sc *crb_sc;
485 	struct tpm_sc *sc;
486 	uint32_t mask, curr_cmd;
487 	int timeout, bytes_available;
488 
489 	crb_sc = device_get_softc(dev);
490 	sc = &crb_sc->base;
491 
492 	sx_assert(&sc->dev_lock, SA_XLOCKED);
493 
494 	if (length > crb_sc->cmd_buf_size) {
495 		device_printf(dev,
496 		    "Requested transfer is bigger than buffer size\n");
497 		return (E2BIG);
498 	}
499 
500 	if (TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) {
501 		device_printf(dev,
502 		    "Device has Error bit set\n");
503 		return (EIO);
504 	}
505 	if (!tpmcrb_request_locality(sc, 0)) {
506 		device_printf(dev,
507 		    "Failed to obtain locality\n");
508 		return (EIO);
509 	}
510 	/* Clear cancellation bit */
511 	TPM_WRITE_4(dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
512 
513 	/* Switch device to idle state if necessary */
514 	if (!(TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {
515 		if (!tpmcrb_state_idle(crb_sc, true)) {
516 			device_printf(dev,
517 			    "Failed to transition to idle state\n");
518 			return (EIO);
519 		}
520 	}
521 
522 	/* Switch to ready state */
523 	if (!tpmcrb_state_ready(crb_sc, true)) {
524 		device_printf(dev,
525 		    "Failed to transition to ready state\n");
526 		return (EIO);
527 	}
528 
529 	/*
530 	 * Calculate timeout for current command.
531 	 * Command code is passed in bytes 6-10.
532 	 */
533 	curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6]));
534 	timeout = tpm20_get_timeout(curr_cmd);
535 
536 	/* Send command and tell device to process it. */
537 	bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off,
538 	    priv->buf, length);
539 	TPM_WRITE_BARRIER(dev, crb_sc->cmd_off, length);
540 
541 	TPM_WRITE_4(dev, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD);
542 	TPM_WRITE_BARRIER(dev, TPM_CRB_CTRL_START, 4);
543 
544 	if (!tpmcrb_notify_cmdready(crb_sc, timeout)) {
545 		device_printf(dev,
546 		    "Timeout while waiting for device to ready\n");
547 		if (!tpmcrb_cancel_cmd(sc))
548 			return (EIO);
549 	}
550 
551 	mask = ~0;
552 	if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) {
553 		device_printf(dev,
554 		    "Timeout while waiting for device to process cmd\n");
555 		if (!tpmcrb_cancel_cmd(sc))
556 			return (EIO);
557 	}
558 
559 	/* Read response header. Length is passed in bytes 2 - 6. */
560 	bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off,
561 	    priv->buf, TPM_HEADER_SIZE);
562 	bytes_available = be32toh(*(uint32_t *) (&priv->buf[2]));
563 
564 	if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) {
565 		device_printf(dev,
566 		    "Incorrect response size: %d\n",
567 		    bytes_available);
568 		return (EIO);
569 	}
570 
571 	bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
572 	      &priv->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
573 
574 	/*
575 	 * No need to wait for the transition to idle on the way out, we can
576 	 * relinquish locality right away.
577 	 */
578 	if (!tpmcrb_state_idle(crb_sc, false)) {
579 		device_printf(dev,
580 		    "Failed to transition to idle state post-send\n");
581 		return (EIO);
582 	}
583 
584 	tpmcrb_relinquish_locality(sc);
585 	priv->offset = 0;
586 	priv->len = bytes_available;
587 
588 	return (0);
589 }
590 
591 /* StartMethod Implementation Details */
592 
593 /** Pluton **/
594 struct tpmcrb_startmethod_pluton {
595 	uint64_t		sm_startaddr;
596 	uint64_t		sm_replyaddr;
597 };
598 
599 static bool
pluton_attach(struct tpmcrb_sc * crb_sc,void * smdataregion,size_t datasz)600 pluton_attach(struct tpmcrb_sc *crb_sc, void *smdataregion, size_t datasz)
601 {
602 	struct tpmcrb_startmethod_pluton *smdata;
603 	struct tpm_sc *sc;
604 	rman_res_t base_addr, end_addr;
605 
606 	if (datasz < sizeof(*smdata))
607 		return (false);
608 
609 	smdata = smdataregion;
610 	sc = &crb_sc->base;
611 
612 	base_addr = rman_get_start(sc->mem_res);
613 	end_addr = rman_get_end(sc->mem_res);
614 	/* Sanity check */
615 	if (smdata->sm_startaddr < base_addr ||
616 	    smdata->sm_startaddr > end_addr ||
617 	    smdata->sm_replyaddr < base_addr ||
618 	    smdata->sm_replyaddr > end_addr)
619 		return (false);
620 
621 	crb_sc->pluton.start_reg = smdata->sm_startaddr - base_addr;
622 	crb_sc->pluton.reply_reg = smdata->sm_replyaddr - base_addr;
623 	return (true);
624 }
625 
626 static bool
pluton_doorbell(struct tpmcrb_sc * crb_sc,int timeout)627 pluton_doorbell(struct tpmcrb_sc *crb_sc, int timeout)
628 {
629 	struct tpm_sc *sc;
630 	device_t dev;
631 
632 	sc = &crb_sc->base;
633 	dev = sc->dev;
634 	TPM_WRITE_4(dev, crb_sc->pluton.start_reg, 1);
635 	TPM_WRITE_BARRIER(dev, crb_sc->pluton.start_reg, 4);
636 
637 	if (timeout > 0) {
638 		if (!tpm_wait_for_u32(sc, crb_sc->pluton.reply_reg, ~0U, 1,
639 		    timeout))
640 			return (false);
641 	}
642 
643 	return (true);
644 }
645 
646 /* ACPI Driver */
647 static device_method_t	tpmcrb_methods[] = {
648 	DEVMETHOD(device_probe,		tpmcrb_acpi_probe),
649 	DEVMETHOD(device_attach,	tpmcrb_attach),
650 	DEVMETHOD(device_detach,	tpmcrb_detach),
651 	DEVMETHOD(device_shutdown,	tpm20_shutdown),
652 	DEVMETHOD(device_suspend,	tpm20_suspend),
653 	DEVMETHOD(device_resume,	tpm20_resume),
654 	DEVMETHOD(tpm_transmit,		tpmcrb_transmit),
655 	{0, 0}
656 };
657 
658 DEFINE_CLASS_1(tpmcrb, tpmcrb_driver, tpmcrb_methods, sizeof(struct tpmcrb_sc),
659     tpm_bus_driver);
660 
661 DRIVER_MODULE(tpmcrb, acpi, tpmcrb_driver, 0, 0);
662