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 * $FreeBSD: head/sys/dev/tpm/tpm_crb.c 365144 2020-09-01 21:50:31Z mjg $
28 */
29
30 #include "tpm20.h"
31
32 /*
33 * CRB register space as defined in
34 * TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22
35 */
36 #define TPM_LOC_STATE 0x0
37 #define TPM_LOC_CTRL 0x8
38 #define TPM_LOC_STS 0xC
39 #define TPM_CRB_INTF_ID 0x30
40 #define TPM_CRB_CTRL_EXT 0x38
41 #define TPM_CRB_CTRL_REQ 0x40
42 #define TPM_CRB_CTRL_STS 0x44
43 #define TPM_CRB_CTRL_CANCEL 0x48
44 #define TPM_CRB_CTRL_START 0x4C
45 #define TPM_CRB_INT_ENABLE 0x50
46 #define TPM_CRB_INT_STS 0x54
47 #define TPM_CRB_CTRL_CMD_SIZE 0x58
48 #define TPM_CRB_CTRL_CMD_LADDR 0x5C
49 #define TPM_CRB_CTRL_CMD_HADDR 0x60
50 #define TPM_CRB_CTRL_RSP_SIZE 0x64
51 #define TPM_CRB_CTRL_RSP_ADDR 0x68
52 #define TPM_CRB_CTRL_RSP_HADDR 0x6c
53 #define TPM_CRB_DATA_BUFFER 0x80
54
55 #define TPM_LOC_STATE_ESTB BIT(0)
56 #define TPM_LOC_STATE_ASSIGNED BIT(1)
57 #define TPM_LOC_STATE_ACTIVE_MASK 0x9C
58 #define TPM_LOC_STATE_VALID BIT(7)
59
60 #define TPM_CRB_INTF_ID_TYPE_CRB 0x1
61 #define TPM_CRB_INTF_ID_TYPE 0x7
62
63 #define TPM_LOC_CTRL_REQUEST BIT(0)
64 #define TPM_LOC_CTRL_RELINQUISH BIT(1)
65
66 #define TPM_CRB_CTRL_REQ_GO_READY BIT(0)
67 #define TPM_CRB_CTRL_REQ_GO_IDLE BIT(1)
68
69 #define TPM_CRB_CTRL_STS_ERR_BIT BIT(0)
70 #define TPM_CRB_CTRL_STS_IDLE_BIT BIT(1)
71
72 #define TPM_CRB_CTRL_CANCEL_CMD 0x1
73 #define TPM_CRB_CTRL_CANCEL_CLEAR 0x0
74
75 #define TPM_CRB_CTRL_START_CMD BIT(0)
76
77 #define TPM_CRB_INT_ENABLE_BIT BIT(31)
78
79 struct tpmcrb_sc {
80 struct tpm_sc base;
81 bus_size_t cmd_off;
82 bus_size_t rsp_off;
83 size_t cmd_buf_size;
84 size_t rsp_buf_size;
85 };
86
87 int tpmcrb_transmit(struct tpm_sc *sc, size_t size);
88
89 static int tpmcrb_acpi_probe(device_t dev);
90 static int tpmcrb_attach(device_t dev);
91 static int tpmcrb_detach(device_t dev);
92
93 static ACPI_STATUS tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg);
94
95 static bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off,
96 uint32_t mask, uint32_t val, int32_t timeout);
97 static bool tpmcrb_request_locality(struct tpm_sc *sc, int locality);
98 static void tpmcrb_relinquish_locality(struct tpm_sc *sc);
99 static bool tpmcrb_cancel_cmd(struct tpm_sc *sc);
100
101 char *tpmcrb_ids[] = {"MSFT0101", NULL};
102
103 static int
tpmcrb_acpi_probe(device_t dev)104 tpmcrb_acpi_probe(device_t dev)
105 {
106 int err = 0;
107 ACPI_TABLE_TPM23 *tbl;
108 ACPI_STATUS status;
109 if (ACPI_ID_PROBE(device_get_parent(dev), dev, tpmcrb_ids) == NULL) {
110 err = ENXIO;
111 goto fail;
112 }
113 /*Find TPM2 Header*/
114 status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **) &tbl);
115 if(ACPI_FAILURE(status) ||
116 tbl->StartMethod != TPM2_START_METHOD_CRB)
117 err = ENXIO;
118
119 device_set_desc(dev, "Trusted Platform Module 2.0, CRB mode");
120 fail:
121 return (err);
122 }
123
124 static ACPI_STATUS
tpmcrb_fix_buff_offsets(ACPI_RESOURCE * res,void * arg)125 tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg)
126 {
127 struct tpmcrb_sc *crb_sc;
128 size_t length;
129 uint32_t base_addr;
130
131 crb_sc = (struct tpmcrb_sc *)arg;
132
133 if (res->Type != ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
134 return (AE_OK);
135
136 base_addr = res->Data.FixedMemory32.Address;
137 length = res->Data.FixedMemory32.AddressLength;
138
139 if (crb_sc->cmd_off > base_addr && crb_sc->cmd_off < base_addr + length)
140 crb_sc->cmd_off -= base_addr;
141 if (crb_sc->rsp_off > base_addr && crb_sc->rsp_off < base_addr + length)
142 crb_sc->rsp_off -= base_addr;
143
144 return (AE_OK);
145 }
146
147 static int
tpmcrb_attach(device_t dev)148 tpmcrb_attach(device_t dev)
149 {
150 struct tpmcrb_sc *crb_sc;
151 struct tpm_sc *sc;
152 ACPI_HANDLE handle;
153 ACPI_STATUS status;
154 int result;
155
156 crb_sc = device_get_softc(dev);
157 sc = &crb_sc->base;
158 handle = acpi_get_handle(dev);
159
160 sc->dev = dev;
161
162 sc->mem_rid = 0;
163 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
164 RF_ACTIVE);
165 if (sc->mem_res == NULL)
166 return (ENXIO);
167
168 if(!tpmcrb_request_locality(sc, 0)) {
169 bus_release_resource(dev, SYS_RES_MEMORY,
170 sc->mem_rid, sc->mem_res);
171 return (ENXIO);
172 }
173
174 /*
175 * Disable all interrupts for now, since I don't have a device that
176 * works in CRB mode and supports them.
177 */
178 AND4(sc, TPM_CRB_INT_ENABLE, ~TPM_CRB_INT_ENABLE_BIT);
179 sc->interrupts = false;
180
181 /*
182 * Read addresses of Tx/Rx buffers and their sizes. Note that they
183 * can be implemented by a single buffer. Also for some reason CMD
184 * addr is stored in two 4 byte neighboring registers, whereas RSP is
185 * stored in a single 8 byte one.
186 */
187 #ifdef __amd64__
188 crb_sc->rsp_off = RD8(sc, TPM_CRB_CTRL_RSP_ADDR);
189 #else
190 crb_sc->rsp_off = RD4(sc, TPM_CRB_CTRL_RSP_ADDR);
191 crb_sc->rsp_off |= ((uint64_t) RD4(sc, TPM_CRB_CTRL_RSP_HADDR) << 32);
192 #endif
193 crb_sc->cmd_off = RD4(sc, TPM_CRB_CTRL_CMD_LADDR);
194 crb_sc->cmd_off |= ((uint64_t) RD4(sc, TPM_CRB_CTRL_CMD_HADDR) << 32);
195 crb_sc->cmd_buf_size = RD4(sc, TPM_CRB_CTRL_CMD_SIZE);
196 crb_sc->rsp_buf_size = RD4(sc, TPM_CRB_CTRL_RSP_SIZE);
197
198 tpmcrb_relinquish_locality(sc);
199
200 /* Emulator returns address in acpi space instead of an offset */
201 status = AcpiWalkResources(handle, "_CRS", tpmcrb_fix_buff_offsets,
202 (void *)crb_sc);
203 if (ACPI_FAILURE(status)) {
204 tpmcrb_detach(dev);
205 return (ENXIO);
206 }
207
208 if (crb_sc->rsp_off == crb_sc->cmd_off) {
209 /*
210 * If Tx/Rx buffers are implemented as one they have to be of
211 * same size
212 */
213 if (crb_sc->cmd_buf_size != crb_sc->rsp_buf_size) {
214 device_printf(sc->dev,
215 "Overlapping Tx/Rx buffers have different sizes\n");
216 tpmcrb_detach(dev);
217 return (ENXIO);
218 }
219 }
220
221 sc->transmit = tpmcrb_transmit;
222
223 result = tpm20_init(sc);
224 if (result != 0)
225 tpmcrb_detach(dev);
226
227 return (result);
228 }
229
230 static int
tpmcrb_detach(device_t dev)231 tpmcrb_detach(device_t dev)
232 {
233 struct tpm_sc *sc;
234
235 sc = device_get_softc(dev);
236 tpm20_release(sc);
237
238 if (sc->mem_res != NULL)
239 bus_release_resource(dev, SYS_RES_MEMORY,
240 sc->mem_rid, sc->mem_res);
241
242 return (0);
243 }
244
245 static bool
tpm_wait_for_u32(struct tpm_sc * sc,bus_size_t off,uint32_t mask,uint32_t val,int32_t timeout)246 tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off, uint32_t mask, uint32_t val,
247 int32_t timeout)
248 {
249
250 /* Check for condition */
251 if ((RD4(sc, off) & mask) == val)
252 return (true);
253
254 while (timeout > 0) {
255 if ((RD4(sc, off) & mask) == val)
256 return (true);
257
258 tsleep(tpm_wait_for_u32, 0, "TPM in polling mode", 1);
259 timeout -= ustick;
260 }
261 return (false);
262 }
263
264 static bool
tpmcrb_request_locality(struct tpm_sc * sc,int locality)265 tpmcrb_request_locality(struct tpm_sc *sc, int locality)
266 {
267 uint32_t mask;
268
269 /* Currently we only support Locality 0 */
270 if (locality != 0)
271 return (false);
272
273 mask = TPM_LOC_STATE_VALID | TPM_LOC_STATE_ASSIGNED;
274
275 OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_REQUEST);
276 if (!tpm_wait_for_u32(sc, TPM_LOC_STATE, mask, mask, TPM_TIMEOUT_C))
277 return (false);
278
279 return (true);
280 }
281
282 static void
tpmcrb_relinquish_locality(struct tpm_sc * sc)283 tpmcrb_relinquish_locality(struct tpm_sc *sc)
284 {
285
286 OR4(sc, TPM_LOC_CTRL, TPM_LOC_CTRL_RELINQUISH);
287 }
288
289 static bool
tpmcrb_cancel_cmd(struct tpm_sc * sc)290 tpmcrb_cancel_cmd(struct tpm_sc *sc)
291 {
292 uint32_t mask = ~0;
293
294 WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CMD);
295 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START,
296 mask, ~mask, TPM_TIMEOUT_B)) {
297 device_printf(sc->dev,
298 "Device failed to cancel command\n");
299 return (false);
300 }
301
302 WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
303 return (true);
304 }
305
306 int
tpmcrb_transmit(struct tpm_sc * sc,size_t length)307 tpmcrb_transmit(struct tpm_sc *sc, size_t length)
308 {
309 struct tpmcrb_sc *crb_sc;
310 uint32_t mask, curr_cmd;
311 int timeout, bytes_available;
312
313 crb_sc = (struct tpmcrb_sc *)sc;
314
315 KKASSERT(lockstatus(&sc->dev_lock, curthread) == LK_EXCLUSIVE);
316
317 if (length > crb_sc->cmd_buf_size) {
318 device_printf(sc->dev,
319 "Requested transfer is bigger than buffer size\n");
320 return (E2BIG);
321 }
322
323 if (RD4(sc, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_ERR_BIT) {
324 device_printf(sc->dev,
325 "Device has Error bit set\n");
326 return (EIO);
327 }
328 if (!tpmcrb_request_locality(sc, 0)) {
329 device_printf(sc->dev,
330 "Failed to obtain locality\n");
331 return (EIO);
332 }
333 /* Clear cancellation bit */
334 WR4(sc, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR);
335
336 /* Switch device to idle state if necessary */
337 if (!(RD4(sc, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {
338 OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
339
340 mask = TPM_CRB_CTRL_STS_IDLE_BIT;
341 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
342 mask, mask, TPM_TIMEOUT_C)) {
343 device_printf(sc->dev,
344 "Failed to transition to idle state\n");
345 return (EIO);
346 }
347 }
348 /* Switch to ready state */
349 OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
350
351 mask = TPM_CRB_CTRL_REQ_GO_READY;
352 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
353 mask, !mask, TPM_TIMEOUT_C)) {
354 device_printf(sc->dev,
355 "Failed to transition to ready state\n");
356 return (EIO);
357 }
358
359 /*
360 * Calculate timeout for current command.
361 * Command code is passed in bytes 6-10.
362 */
363 curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6]));
364 timeout = tpm20_get_timeout(curr_cmd);
365
366 /* Send command and tell device to process it. */
367 bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off,
368 sc->buf, length);
369 bus_barrier(sc->mem_res, crb_sc->cmd_off,
370 length, BUS_SPACE_BARRIER_WRITE);
371
372 WR4(sc, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD);
373 bus_barrier(sc->mem_res, TPM_CRB_CTRL_START,
374 4, BUS_SPACE_BARRIER_WRITE);
375
376 mask = ~0;
377 if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) {
378 device_printf(sc->dev,
379 "Timeout while waiting for device to process cmd\n");
380 if (!tpmcrb_cancel_cmd(sc))
381 return (EIO);
382 }
383
384 /* Read response header. Length is passed in bytes 2 - 6. */
385 bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off,
386 sc->buf, TPM_HEADER_SIZE);
387 bytes_available = be32toh(*(uint32_t *) (&sc->buf[2]));
388
389 if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) {
390 device_printf(sc->dev,
391 "Incorrect response size: %d\n",
392 bytes_available);
393 return (EIO);
394 }
395
396 bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
397 &sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
398
399 OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
400
401 tpmcrb_relinquish_locality(sc);
402 sc->pending_data_length = bytes_available;
403
404 return (0);
405 }
406
407 /* ACPI Driver */
408 static device_method_t tpmcrb_methods[] = {
409 DEVMETHOD(device_probe, tpmcrb_acpi_probe),
410 DEVMETHOD(device_attach, tpmcrb_attach),
411 DEVMETHOD(device_detach, tpmcrb_detach),
412 DEVMETHOD(device_shutdown, tpm20_shutdown),
413 DEVMETHOD(device_suspend, tpm20_suspend),
414 {0, 0}
415 };
416 static driver_t tpmcrb_driver = {
417 "tpmcrb", tpmcrb_methods, sizeof(struct tpmcrb_sc),
418 };
419
420 devclass_t tpmcrb_devclass;
421 DRIVER_MODULE(tpmcrb, acpi, tpmcrb_driver, tpmcrb_devclass, NULL, NULL);
422