xref: /dragonfly/sys/dev/crypto/tpm/tpm_crb.c (revision 959366edc6ceee964a31f71baf4f38d75e0f167c)
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