]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/tpm/tpm_crb.c
Merge release 1.14 of bsnmp.
[FreeBSD/FreeBSD.git] / sys / dev / tpm / tpm_crb.c
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 __FBSDID("$FreeBSD$");
30
31 #include "tpm20.h"
32
33 /*
34  * CRB register space as defined in
35  * TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22
36  */
37 #define TPM_LOC_STATE                   0x0
38 #define TPM_LOC_CTRL                    0x8
39 #define TPM_LOC_STS                     0xC
40 #define TPM_CRB_INTF_ID                 0x30
41 #define TPM_CRB_CTRL_EXT                0x38
42 #define TPM_CRB_CTRL_REQ                0x40
43 #define TPM_CRB_CTRL_STS                0x44
44 #define TPM_CRB_CTRL_CANCEL             0x48
45 #define TPM_CRB_CTRL_START              0x4C
46 #define TPM_CRB_INT_ENABLE              0x50
47 #define TPM_CRB_INT_STS                 0x54
48 #define TPM_CRB_CTRL_CMD_SIZE           0x58
49 #define TPM_CRB_CTRL_CMD_LADDR          0x5C
50 #define TPM_CRB_CTRL_CMD_HADDR          0x60
51 #define TPM_CRB_CTRL_RSP_SIZE           0x64
52 #define TPM_CRB_CTRL_RSP_ADDR           0x68
53 #define TPM_CRB_CTRL_RSP_HADDR          0x6c
54 #define TPM_CRB_DATA_BUFFER             0x80
55
56 #define TPM_LOC_STATE_ESTB              BIT(0)
57 #define TPM_LOC_STATE_ASSIGNED          BIT(1)
58 #define TPM_LOC_STATE_ACTIVE_MASK       0x9C
59 #define TPM_LOC_STATE_VALID             BIT(7)
60
61 #define TPM_CRB_INTF_ID_TYPE_CRB        0x1
62 #define TPM_CRB_INTF_ID_TYPE            0x7
63
64 #define TPM_LOC_CTRL_REQUEST            BIT(0)
65 #define TPM_LOC_CTRL_RELINQUISH         BIT(1)
66
67 #define TPM_CRB_CTRL_REQ_GO_READY       BIT(0)
68 #define TPM_CRB_CTRL_REQ_GO_IDLE        BIT(1)
69
70 #define TPM_CRB_CTRL_STS_ERR_BIT        BIT(0)
71 #define TPM_CRB_CTRL_STS_IDLE_BIT       BIT(1)
72
73 #define TPM_CRB_CTRL_CANCEL_CMD         0x1
74 #define TPM_CRB_CTRL_CANCEL_CLEAR       0x0
75
76 #define TPM_CRB_CTRL_START_CMD          BIT(0)
77
78 #define TPM_CRB_INT_ENABLE_BIT          BIT(31)
79
80 struct tpmcrb_sc {
81         struct tpm_sc   base;
82         bus_size_t      cmd_off;
83         bus_size_t      rsp_off;
84         size_t          cmd_buf_size;
85         size_t          rsp_buf_size;
86 };
87
88
89 int tpmcrb_transmit(struct tpm_sc *sc, size_t size);
90
91 static int tpmcrb_acpi_probe(device_t dev);
92 static int tpmcrb_attach(device_t dev);
93 static int tpmcrb_detach(device_t dev);
94
95 static ACPI_STATUS tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg);
96
97 static bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off,
98     uint32_t mask, uint32_t val, int32_t timeout);
99 static bool tpmcrb_request_locality(struct tpm_sc *sc, int locality);
100 static void tpmcrb_relinquish_locality(struct tpm_sc *sc);
101 static bool tpmcrb_cancel_cmd(struct tpm_sc *sc);
102
103 char *tpmcrb_ids[] = {"MSFT0101", NULL};
104
105 static int
106 tpmcrb_acpi_probe(device_t dev)
107 {
108         int err;
109         ACPI_TABLE_TPM23 *tbl;
110         ACPI_STATUS status;
111         err = ACPI_ID_PROBE(device_get_parent(dev), dev, tpmcrb_ids, NULL);
112         if (err > 0)
113                 return (err);
114         /*Find TPM2 Header*/
115         status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **) &tbl);
116         if(ACPI_FAILURE(status) ||
117            tbl->StartMethod != TPM2_START_METHOD_CRB)
118                 err = ENXIO;
119
120         device_set_desc(dev, "Trusted Platform Module 2.0, CRB mode");
121         return (err);
122 }
123
124 static ACPI_STATUS
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
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
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
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                 pause("TPM in polling mode", 1);
259                 timeout -= tick;
260         }
261         return (false);
262 }
263
264 static bool
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
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
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
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         sx_assert(&sc->dev_lock, SA_XLOCKED);
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, 0, 0);