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