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/detach callbacks */
80 typedef bool (sm_attach_t)(struct tpmcrb_sc *, void *, size_t);
81 typedef void (sm_detach_t)(struct tpmcrb_sc *);
82 /* State change notification (timeout == 0 for 'no timeout') */
83 typedef bool (sm_statechange_t)(struct tpmcrb_sc *, int);
84
85 struct tpmcrb_sm_cfg {
86 sm_attach_t *sm_attach;
87 sm_detach_t *sm_detach;
88 sm_statechange_t *sm_statechange;
89 sm_statechange_t *sm_cmdready;
90 };
91
92 static sm_attach_t pluton_attach;
93 static sm_detach_t pluton_detach;
94 static sm_statechange_t pluton_doorbell;
95
96 static const struct tpmcrb_sm_cfg_map {
97 int acpi_sm;
98 const char *desc;
99 const struct tpmcrb_sm_cfg sm_cfg;
100 } tpmcrb_sm_cfg_map[] = {
101 {
102 .acpi_sm = TPM2_START_METHOD_CRB,
103 .desc = "Trusted Platform Module 2.0, CRB mode",
104 .sm_cfg = { NULL }, /* No notifications required */
105 },
106 {
107 .acpi_sm = ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON,
108 .desc = "Trusted Platform Module 2.0, CRB mode (Pluton)",
109 .sm_cfg = {
110 .sm_attach = &pluton_attach,
111 .sm_detach = &pluton_detach,
112 .sm_statechange = &pluton_doorbell,
113 .sm_cmdready = &pluton_doorbell,
114 },
115 },
116 };
117
118 struct tpmcrb_sc {
119 struct tpm_sc base;
120 const struct tpmcrb_sm_cfg *sm_cfg;
121 union {
122 /*
123 * StartMethod data. The Pluton start/reply mailbox
124 * registers may live outside of the _CRS window, so they get
125 * their own bus_space mapping.
126 */
127 struct {
128 bus_space_tag_t bst;
129 bus_space_handle_t start_bsh;
130 bus_space_handle_t reply_bsh;
131 } pluton;
132 };
133 bus_size_t cmd_off;
134 bus_size_t rsp_off;
135 size_t cmd_buf_size;
136 size_t rsp_buf_size;
137 };
138
139 int tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t size);
140
141 static int tpmcrb_acpi_probe(device_t dev);
142 static int tpmcrb_attach(device_t dev);
143 static int tpmcrb_detach(device_t dev);
144
145 static ACPI_STATUS tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg);
146
147 static bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off,
148 uint32_t mask, uint32_t val, int32_t timeout);
149 static bool tpmcrb_request_locality(struct tpm_sc *sc, int locality);
150 static void tpmcrb_relinquish_locality(struct tpm_sc *sc);
151 static bool tpmcrb_cancel_cmd(struct tpm_sc *sc);
152
153 char *tpmcrb_ids[] = {"MSFT0101", NULL};
154
155 static const struct tpmcrb_sm_cfg_map *
tpmcrb_acpi_startmethod_cfg(int method)156 tpmcrb_acpi_startmethod_cfg(int method)
157 {
158 const struct tpmcrb_sm_cfg_map *entry;
159
160 for (size_t i = 0; i < nitems(tpmcrb_sm_cfg_map); i++) {
161 entry = &tpmcrb_sm_cfg_map[i];
162
163 if (method == entry->acpi_sm)
164 return (entry);
165 }
166
167 return (NULL);
168 }
169
170 static int
tpmcrb_acpi_probe(device_t dev)171 tpmcrb_acpi_probe(device_t dev)
172 {
173 int err, smethod;
174 const struct tpmcrb_sm_cfg_map *sm_cfg_map;
175 ACPI_TABLE_TPM23 *tbl;
176 ACPI_STATUS status;
177
178 err = ACPI_ID_PROBE(device_get_parent(dev), dev, tpmcrb_ids, NULL);
179 if (err > 0)
180 return (err);
181 /*Find TPM2 Header*/
182 status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **) &tbl);
183 if (ACPI_FAILURE(status))
184 return (ENXIO);
185
186 smethod = tbl->StartMethod;
187 AcpiPutTable((ACPI_TABLE_HEADER *)tbl);
188
189 sm_cfg_map = tpmcrb_acpi_startmethod_cfg(smethod);
190 if (sm_cfg_map == NULL)
191 return (ENXIO);
192
193 device_set_desc(dev, sm_cfg_map->desc);
194 return (0);
195 }
196
197 static ACPI_STATUS
tpmcrb_fix_buff_offsets(ACPI_RESOURCE * res,void * arg)198 tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg)
199 {
200 struct tpmcrb_sc *crb_sc;
201 size_t length;
202 uint32_t base_addr;
203
204 crb_sc = (struct tpmcrb_sc *)arg;
205
206 if (res->Type != ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
207 return (AE_OK);
208
209 base_addr = res->Data.FixedMemory32.Address;
210 length = res->Data.FixedMemory32.AddressLength;
211
212 if (crb_sc->cmd_off > base_addr && crb_sc->cmd_off < base_addr + length)
213 crb_sc->cmd_off -= base_addr;
214 if (crb_sc->rsp_off > base_addr && crb_sc->rsp_off < base_addr + length)
215 crb_sc->rsp_off -= base_addr;
216
217 return (AE_OK);
218 }
219
220 static bool
tpmcrb_attach_startmethod(struct tpmcrb_sc * crb_sc)221 tpmcrb_attach_startmethod(struct tpmcrb_sc *crb_sc)
222 {
223 const struct tpmcrb_sm_cfg_map *sm_cfg_map;
224 const struct tpmcrb_sm_cfg *sm_cfg;
225 ACPI_TABLE_TPM23 *tbl;
226 void *smdata;
227 ACPI_STATUS status;
228 bool ret;
229
230 /*
231 * Grab what we need from the StartMethod.
232 */
233 status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **)(void **)&tbl);
234 if (ACPI_FAILURE(status))
235 return (false);
236
237 sm_cfg_map = tpmcrb_acpi_startmethod_cfg(tbl->StartMethod);
238 MPASS(sm_cfg_map != NULL);
239 sm_cfg = &sm_cfg_map->sm_cfg;
240
241 crb_sc->sm_cfg = sm_cfg;
242 smdata = tbl + 1;
243 if (sm_cfg->sm_attach != NULL) {
244 ret = (*sm_cfg->sm_attach)(crb_sc, smdata,
245 tbl->Header.Length - sizeof(*tbl));
246 } else {
247 ret = true;
248 }
249
250 AcpiPutTable((ACPI_TABLE_HEADER *)tbl);
251 return (ret);
252 }
253
254 static int
tpmcrb_attach(device_t dev)255 tpmcrb_attach(device_t dev)
256 {
257 struct tpmcrb_sc *crb_sc;
258 struct tpm_sc *sc;
259 ACPI_HANDLE handle;
260 ACPI_STATUS status;
261 int result;
262
263 crb_sc = device_get_softc(dev);
264 sc = &crb_sc->base;
265 handle = acpi_get_handle(dev);
266 sc->dev = dev;
267
268 sx_init(&sc->dev_lock, "TPM driver lock");
269
270 sc->mem_rid = 0;
271 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
272 RF_ACTIVE);
273 if (sc->mem_res == NULL) {
274 tpmcrb_detach(dev);
275 return (ENXIO);
276 }
277
278 if (!tpmcrb_attach_startmethod(crb_sc)) {
279 tpmcrb_detach(dev);
280 return (ENXIO);
281 }
282
283 if(!tpmcrb_request_locality(sc, 0)) {
284 tpmcrb_detach(dev);
285 return (ENXIO);
286 }
287
288 /*
289 * Disable all interrupts for now, since I don't have a device that
290 * works in CRB mode and supports them.
291 */
292 AND4(sc, TPM_CRB_INT_ENABLE, ~TPM_CRB_INT_ENABLE_BIT);
293 sc->interrupts = false;
294
295 /*
296 * Read addresses of Tx/Rx buffers and their sizes. Note that they
297 * can be implemented by a single buffer. Also for some reason CMD
298 * addr is stored in two 4 byte neighboring registers, whereas RSP is
299 * stored in a single 8 byte one.
300 */
301 #ifdef __amd64__
302 crb_sc->rsp_off = TPM_READ_8(sc->dev, TPM_CRB_CTRL_RSP_ADDR);
303 #else
304 crb_sc->rsp_off = TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_ADDR);
305 crb_sc->rsp_off |= ((uint64_t) TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_HADDR) << 32);
306 #endif
307 crb_sc->cmd_off = TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_LADDR);
308 crb_sc->cmd_off |= ((uint64_t) TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_HADDR) << 32);
309 crb_sc->cmd_buf_size = TPM_READ_4(sc->dev, TPM_CRB_CTRL_CMD_SIZE);
310 crb_sc->rsp_buf_size = TPM_READ_4(sc->dev, TPM_CRB_CTRL_RSP_SIZE);
311
312 tpmcrb_relinquish_locality(sc);
313
314 /* Emulator returns address in acpi space instead of an offset */
315 status = AcpiWalkResources(handle, "_CRS", tpmcrb_fix_buff_offsets,
316 (void *)crb_sc);
317 if (ACPI_FAILURE(status)) {
318 tpmcrb_detach(dev);
319 return (ENXIO);
320 }
321
322 if (crb_sc->rsp_off == crb_sc->cmd_off) {
323 /*
324 * If Tx/Rx buffers are implemented as one they have to be of
325 * same size
326 */
327 if (crb_sc->cmd_buf_size != crb_sc->rsp_buf_size) {
328 device_printf(sc->dev,
329 "Overlapping Tx/Rx buffers have different sizes\n");
330 tpmcrb_detach(dev);
331 return (ENXIO);
332 }
333 }
334
335 result = tpm20_init(sc);
336 if (result != 0)
337 tpmcrb_detach(dev);
338
339 return (result);
340 }
341
342 static int
tpmcrb_detach(device_t dev)343 tpmcrb_detach(device_t dev)
344 {
345 struct tpmcrb_sc *crb_sc;
346 struct tpm_sc *sc;
347
348 crb_sc = device_get_softc(dev);
349 sc = &crb_sc->base;
350 tpm20_release(sc);
351
352 if (crb_sc->sm_cfg != NULL && crb_sc->sm_cfg->sm_detach != NULL)
353 (*crb_sc->sm_cfg->sm_detach)(crb_sc);
354
355 if (sc->mem_res != NULL)
356 bus_release_resource(dev, SYS_RES_MEMORY,
357 sc->mem_rid, sc->mem_res);
358
359 return (0);
360 }
361
362 static bool
tpm_wait_for_u32(struct tpm_sc * sc,bus_size_t off,uint32_t mask,uint32_t val,int32_t timeout)363 tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off, uint32_t mask, uint32_t val,
364 int32_t timeout)
365 {
366
367 /* Check for condition */
368 if ((TPM_READ_4(sc->dev, off) & mask) == val)
369 return (true);
370
371 while (timeout > 0) {
372 if ((TPM_READ_4(sc->dev, off) & mask) == val)
373 return (true);
374
375 pause("TPM in polling mode", 1);
376 timeout -= tick;
377 }
378 return (false);
379 }
380
381 static bool
tpmcrb_request_locality(struct tpm_sc * sc,int locality)382 tpmcrb_request_locality(struct tpm_sc *sc, int locality)
383 {
384 uint32_t mask;
385
386 /* Currently we only support Locality 0 */
387 if (locality != 0)
388 return (false);
389
390 mask = TPM_LOC_STATE_VALID | TPM_LOC_STATE_ASSIGNED;
391
392 OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_REQUEST);
393 if (!tpm_wait_for_u32(sc, TPM_LOC_STATE, mask, mask, TPM_TIMEOUT_C))
394 return (false);
395
396 return (true);
397 }
398
399 static void
tpmcrb_relinquish_locality(struct tpm_sc * sc)400 tpmcrb_relinquish_locality(struct tpm_sc *sc)
401 {
402
403 OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_RELINQUISH);
404 }
405
406 static bool
tpmcrb_cancel_cmd(struct tpm_sc * sc)407 tpmcrb_cancel_cmd(struct tpm_sc *sc)
408 {
409 uint32_t mask = ~0;
410
411 TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CMD);
412 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START,
413 mask, ~mask, TPM_TIMEOUT_B)) {
414 device_printf(sc->dev,
415 "Device failed to cancel command\n");
416 return (false);
417 }
418
419 TPM_WRITE_4(sc->dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
420 return (true);
421 }
422
423 static bool
tpmcrb_notify_cmdready(struct tpmcrb_sc * crb_sc,int timeout)424 tpmcrb_notify_cmdready(struct tpmcrb_sc *crb_sc, int timeout)
425 {
426 sm_statechange_t *cmdready_fn;
427
428 cmdready_fn = crb_sc->sm_cfg->sm_cmdready;
429 if (cmdready_fn == NULL)
430 return (true);
431
432 return ((*cmdready_fn)(crb_sc, timeout));
433 }
434
435 static bool
tpmcrb_notify_state_changing(struct tpmcrb_sc * crb_sc,int timeout)436 tpmcrb_notify_state_changing(struct tpmcrb_sc *crb_sc, int timeout)
437 {
438 sm_statechange_t *statechange_fn;
439
440 statechange_fn = crb_sc->sm_cfg->sm_statechange;
441 if (statechange_fn == NULL)
442 return (true);
443
444 return ((*statechange_fn)(crb_sc, timeout));
445 }
446
447 static bool
tpmcrb_state_idle(struct tpmcrb_sc * crb_sc,bool wait)448 tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait)
449 {
450 struct tpm_sc *sc;
451 int mask, timeout;
452
453 timeout = wait ? TPM_TIMEOUT_C : 0;
454
455 sc = &crb_sc->base;
456 OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
457
458 if (!tpmcrb_notify_state_changing(crb_sc, timeout))
459 return (false);
460
461 if (timeout > 0) {
462 mask = TPM_CRB_CTRL_STS_IDLE_BIT;
463 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, mask,
464 timeout))
465 return (false);
466 }
467
468 return (true);
469 }
470
471 static bool
tpmcrb_state_ready(struct tpmcrb_sc * crb_sc,bool wait)472 tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait)
473 {
474 struct tpm_sc *sc;
475 int mask, timeout;
476
477 timeout = wait ? TPM_TIMEOUT_C : 0;
478
479 sc = &crb_sc->base;
480 OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
481
482 if (!tpmcrb_notify_state_changing(crb_sc, timeout))
483 return (false);
484
485 if (timeout > 0) {
486 mask = TPM_CRB_CTRL_REQ_GO_READY;
487 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, !mask,
488 timeout))
489 return (false);
490 }
491
492 return (true);
493 }
494
495 int
tpmcrb_transmit(device_t dev,struct tpm_priv * priv,size_t length)496 tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length)
497 {
498 struct tpmcrb_sc *crb_sc;
499 struct tpm_sc *sc;
500 uint32_t mask, curr_cmd;
501 int bytes_available, error, timeout;
502 bool command_started, locality;
503
504 crb_sc = device_get_softc(dev);
505 sc = &crb_sc->base;
506
507 sx_assert(&sc->dev_lock, SA_XLOCKED);
508 command_started = false;
509 locality = false;
510
511 if (length > crb_sc->cmd_buf_size) {
512 device_printf(dev,
513 "Requested transfer is bigger than buffer size\n");
514 return (E2BIG);
515 }
516
517 if (!tpmcrb_request_locality(sc, 0)) {
518 device_printf(dev,
519 "Failed to obtain locality\n");
520 return (EIO);
521 }
522 locality = true;
523
524 /*
525 * Only check for the error once we own the locality: some
526 * implementations do not return meaningful values in the control area
527 * before then. An AMD Pluton fTPM using the plain CRB start method
528 * reads all-ones, which looks like a permanently stuck tpmSts.
529 */
530 if (TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) {
531 device_printf(dev,
532 "Device has Error bit set\n");
533 error = EIO;
534 goto out;
535 }
536 /* Clear cancellation bit */
537 TPM_WRITE_4(dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
538
539 /* Switch device to idle state if necessary */
540 if (!(TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {
541 if (!tpmcrb_state_idle(crb_sc, true)) {
542 device_printf(dev,
543 "Failed to transition to idle state\n");
544 error = EIO;
545 goto out;
546 }
547 }
548
549 /* Switch to ready state */
550 if (!tpmcrb_state_ready(crb_sc, true)) {
551 device_printf(dev,
552 "Failed to transition to ready state\n");
553 error = EIO;
554 goto out;
555 }
556
557 /*
558 * Calculate timeout for current command.
559 * Command code is passed in bytes 6-10.
560 */
561 curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6]));
562 timeout = tpm20_get_timeout(curr_cmd);
563
564 /* Send command and tell device to process it. */
565 bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off,
566 priv->buf, length);
567 TPM_WRITE_BARRIER(dev, crb_sc->cmd_off, length);
568
569 TPM_WRITE_4(dev, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD);
570 TPM_WRITE_BARRIER(dev, TPM_CRB_CTRL_START, 4);
571 command_started = true;
572
573 if (!tpmcrb_notify_cmdready(crb_sc, timeout)) {
574 device_printf(dev,
575 "Timeout while waiting for device to ready\n");
576 if (!tpmcrb_cancel_cmd(sc)) {
577 error = EIO;
578 goto out;
579 }
580 }
581
582 mask = ~0;
583 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) {
584 device_printf(dev,
585 "Timeout while waiting for device to process cmd\n");
586 if (!tpmcrb_cancel_cmd(sc)) {
587 error = EIO;
588 goto out;
589 }
590 }
591
592 /* Read response header. Length is passed in bytes 2 - 6. */
593 bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off,
594 priv->buf, TPM_HEADER_SIZE);
595 bytes_available = be32toh(*(uint32_t *) (&priv->buf[2]));
596
597 if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) {
598 device_printf(dev,
599 "Incorrect response size: %d\n",
600 bytes_available);
601 error = EIO;
602 goto out;
603 }
604
605 bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
606 &priv->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
607
608 priv->offset = 0;
609 priv->len = bytes_available;
610 error = 0;
611
612 out:
613 if (locality) {
614 if (error != 0 && command_started &&
615 (TPM_READ_4(dev, TPM_CRB_CTRL_START) &
616 TPM_CRB_CTRL_START_CMD) != 0)
617 (void)tpmcrb_cancel_cmd(sc);
618 if (!tpmcrb_state_idle(crb_sc, false)) {
619 device_printf(dev,
620 "Failed to transition to idle state post-send\n");
621 if (error == 0)
622 error = EIO;
623 }
624 tpmcrb_relinquish_locality(sc);
625 }
626
627 return (error);
628 }
629
630 /* StartMethod Implementation Details */
631
632 /** Pluton **/
633 struct tpmcrb_startmethod_pluton {
634 uint64_t sm_startaddr;
635 uint64_t sm_replyaddr;
636 };
637
638 static bool
pluton_attach(struct tpmcrb_sc * crb_sc,void * smdataregion,size_t datasz)639 pluton_attach(struct tpmcrb_sc *crb_sc, void *smdataregion, size_t datasz)
640 {
641 struct tpmcrb_startmethod_pluton *smdata;
642 struct tpm_sc *sc;
643 bus_space_tag_t bst;
644
645 if (datasz < sizeof(*smdata))
646 return (false);
647
648 smdata = smdataregion;
649 sc = &crb_sc->base;
650
651 /*
652 * The start/reply mailbox registers are not necessarily part of
653 * the CRB register window described by _CRS, so we map them
654 * independently.
655 */
656 bst = rman_get_bustag(sc->mem_res);
657 if (bus_space_map(bst, smdata->sm_startaddr, sizeof(uint32_t), 0,
658 &crb_sc->pluton.start_bsh) != 0) {
659 device_printf(sc->dev,
660 "Failed to map Pluton start register at %#jx\n",
661 (uintmax_t)smdata->sm_startaddr);
662 return (false);
663 }
664
665 if (bus_space_map(bst, smdata->sm_replyaddr, sizeof(uint32_t), 0,
666 &crb_sc->pluton.reply_bsh) != 0) {
667 device_printf(sc->dev,
668 "Failed to map Pluton reply register at %#jx\n",
669 (uintmax_t)smdata->sm_replyaddr);
670 bus_space_unmap(bst, crb_sc->pluton.start_bsh,
671 sizeof(uint32_t));
672 return (false);
673 }
674
675 crb_sc->pluton.bst = bst;
676 return (true);
677 }
678
679 static void
pluton_detach(struct tpmcrb_sc * crb_sc)680 pluton_detach(struct tpmcrb_sc *crb_sc)
681 {
682
683 if (crb_sc->pluton.bst == 0)
684 return;
685
686 bus_space_unmap(crb_sc->pluton.bst, crb_sc->pluton.start_bsh,
687 sizeof(uint32_t));
688 bus_space_unmap(crb_sc->pluton.bst, crb_sc->pluton.reply_bsh,
689 sizeof(uint32_t));
690 }
691
692 static bool
pluton_wait_reply(struct tpmcrb_sc * crb_sc,int32_t timeout)693 pluton_wait_reply(struct tpmcrb_sc *crb_sc, int32_t timeout)
694 {
695 for (;;) {
696 /*
697 * Always read at least once, and try one more time after we hit
698 * the timeout.
699 */
700 if (bus_space_read_4(crb_sc->pluton.bst,
701 crb_sc->pluton.reply_bsh, 0) == 1)
702 return (true);
703 else if (timeout <= 0)
704 break;
705
706 pause("TPM in polling mode", 1);
707 timeout -= tick;
708 }
709
710 return (false);
711 }
712
713 static bool
pluton_doorbell(struct tpmcrb_sc * crb_sc,int timeout)714 pluton_doorbell(struct tpmcrb_sc *crb_sc, int timeout)
715 {
716 bus_space_write_4(crb_sc->pluton.bst, crb_sc->pluton.start_bsh, 0, 1);
717 bus_space_barrier(crb_sc->pluton.bst, crb_sc->pluton.start_bsh, 0,
718 sizeof(uint32_t), BUS_SPACE_BARRIER_WRITE);
719
720 /*
721 * We assume at timeout == 0 that they're not really interested in a
722 * reply immediately. Otherwise, we poll for a reply at least once,
723 * even with low timeouts.
724 */
725 if (timeout <= 0)
726 return (true);
727 return (pluton_wait_reply(crb_sc, timeout));
728 }
729
730 /* ACPI Driver */
731 static device_method_t tpmcrb_methods[] = {
732 DEVMETHOD(device_probe, tpmcrb_acpi_probe),
733 DEVMETHOD(device_attach, tpmcrb_attach),
734 DEVMETHOD(device_detach, tpmcrb_detach),
735 DEVMETHOD(device_shutdown, tpm20_shutdown),
736 DEVMETHOD(device_suspend, tpm20_suspend),
737 DEVMETHOD(device_resume, tpm20_resume),
738 DEVMETHOD(tpm_transmit, tpmcrb_transmit),
739 {0, 0}
740 };
741
742 DEFINE_CLASS_1(tpmcrb, tpmcrb_driver, tpmcrb_methods, sizeof(struct tpmcrb_sc),
743 tpm_bus_driver);
744
745 DRIVER_MODULE(tpmcrb, acpi, tpmcrb_driver, 0, 0);
746