xref: /freebsd/sys/dev/tpm/tpm20.h (revision a2d5ed9442bb7a030a5c5bcc3e1f6a2acc23eaf7)
1*a2d5ed94SMarcin Wojtas /*-
2*a2d5ed94SMarcin Wojtas  * Copyright (c) 2018 Stormshield.
3*a2d5ed94SMarcin Wojtas  * Copyright (c) 2018 Semihalf.
4*a2d5ed94SMarcin Wojtas  * All rights reserved.
5*a2d5ed94SMarcin Wojtas  *
6*a2d5ed94SMarcin Wojtas  * Redistribution and use in source and binary forms, with or without
7*a2d5ed94SMarcin Wojtas  * modification, are permitted provided that the following conditions
8*a2d5ed94SMarcin Wojtas  * are met:
9*a2d5ed94SMarcin Wojtas  * 1. Redistributions of source code must retain the above copyright
10*a2d5ed94SMarcin Wojtas  *    notice, this list of conditions and the following disclaimer.
11*a2d5ed94SMarcin Wojtas  * 2. Redistributions in binary form must reproduce the above copyright
12*a2d5ed94SMarcin Wojtas  *    notice, this list of conditions and the following disclaimer in the
13*a2d5ed94SMarcin Wojtas  *    documentation and/or other materials provided with the distribution.
14*a2d5ed94SMarcin Wojtas  *
15*a2d5ed94SMarcin Wojtas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*a2d5ed94SMarcin Wojtas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17*a2d5ed94SMarcin Wojtas  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18*a2d5ed94SMarcin Wojtas  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19*a2d5ed94SMarcin Wojtas  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20*a2d5ed94SMarcin Wojtas  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21*a2d5ed94SMarcin Wojtas  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*a2d5ed94SMarcin Wojtas  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23*a2d5ed94SMarcin Wojtas  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*a2d5ed94SMarcin Wojtas  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*a2d5ed94SMarcin Wojtas  * POSSIBILITY OF SUCH DAMAGE.
26*a2d5ed94SMarcin Wojtas  */
27*a2d5ed94SMarcin Wojtas 
28*a2d5ed94SMarcin Wojtas #ifndef _TPM20_H_
29*a2d5ed94SMarcin Wojtas #define _TPM20_H_
30*a2d5ed94SMarcin Wojtas 
31*a2d5ed94SMarcin Wojtas #include <sys/cdefs.h>
32*a2d5ed94SMarcin Wojtas __FBSDID("$FreeBSD$");
33*a2d5ed94SMarcin Wojtas 
34*a2d5ed94SMarcin Wojtas #include <sys/endian.h>
35*a2d5ed94SMarcin Wojtas #include <sys/param.h>
36*a2d5ed94SMarcin Wojtas #include <sys/kernel.h>
37*a2d5ed94SMarcin Wojtas #include <sys/malloc.h>
38*a2d5ed94SMarcin Wojtas #include <sys/proc.h>
39*a2d5ed94SMarcin Wojtas #include <sys/systm.h>
40*a2d5ed94SMarcin Wojtas 
41*a2d5ed94SMarcin Wojtas #include <sys/bus.h>
42*a2d5ed94SMarcin Wojtas #include <sys/callout.h>
43*a2d5ed94SMarcin Wojtas #include <sys/conf.h>
44*a2d5ed94SMarcin Wojtas #include <sys/module.h>
45*a2d5ed94SMarcin Wojtas #include <sys/rman.h>
46*a2d5ed94SMarcin Wojtas #include <sys/sx.h>
47*a2d5ed94SMarcin Wojtas #include <sys/uio.h>
48*a2d5ed94SMarcin Wojtas 
49*a2d5ed94SMarcin Wojtas #include <machine/bus.h>
50*a2d5ed94SMarcin Wojtas #include <machine/md_var.h>
51*a2d5ed94SMarcin Wojtas #include <machine/resource.h>
52*a2d5ed94SMarcin Wojtas 
53*a2d5ed94SMarcin Wojtas #include <contrib/dev/acpica/include/acpi.h>
54*a2d5ed94SMarcin Wojtas #include <contrib/dev/acpica/include/accommon.h>
55*a2d5ed94SMarcin Wojtas #include <dev/acpica/acpivar.h>
56*a2d5ed94SMarcin Wojtas #include "opt_acpi.h"
57*a2d5ed94SMarcin Wojtas 
58*a2d5ed94SMarcin Wojtas #define	BIT(x) (1 << (x))
59*a2d5ed94SMarcin Wojtas 
60*a2d5ed94SMarcin Wojtas /* Timeouts in us */
61*a2d5ed94SMarcin Wojtas #define	TPM_TIMEOUT_A		750000
62*a2d5ed94SMarcin Wojtas #define	TPM_TIMEOUT_B		2000000
63*a2d5ed94SMarcin Wojtas #define	TPM_TIMEOUT_C		200000
64*a2d5ed94SMarcin Wojtas #define	TPM_TIMEOUT_D		30000
65*a2d5ed94SMarcin Wojtas 
66*a2d5ed94SMarcin Wojtas /*
67*a2d5ed94SMarcin Wojtas  * Generating RSA key pair takes ~(10-20s), which is significantly longer than
68*a2d5ed94SMarcin Wojtas  * any timeout defined in spec. Because of that we need a new one.
69*a2d5ed94SMarcin Wojtas  */
70*a2d5ed94SMarcin Wojtas #define	TPM_TIMEOUT_LONG	40000000
71*a2d5ed94SMarcin Wojtas 
72*a2d5ed94SMarcin Wojtas /* List of commands that require TPM_TIMEOUT_LONG time to complete */
73*a2d5ed94SMarcin Wojtas #define	TPM_CC_CreatePrimary	0x00000131
74*a2d5ed94SMarcin Wojtas #define	TPM_CC_Create			0x00000153
75*a2d5ed94SMarcin Wojtas #define	TPM_CC_CreateLoaded		0x00000191
76*a2d5ed94SMarcin Wojtas 
77*a2d5ed94SMarcin Wojtas /* List of commands that require only TPM_TIMEOUT_C time to complete */
78*a2d5ed94SMarcin Wojtas #define TPM_CC_SequenceComplete			0x0000013e
79*a2d5ed94SMarcin Wojtas #define TPM_CC_Startup					0x00000144
80*a2d5ed94SMarcin Wojtas #define TPM_CC_SequenceUpdate			0x0000015c
81*a2d5ed94SMarcin Wojtas #define TPM_CC_GetCapability			0x0000017a
82*a2d5ed94SMarcin Wojtas #define TPM_CC_PCR_Extend				0x00000182
83*a2d5ed94SMarcin Wojtas #define TPM_CC_EventSequenceComplete	0x00000185
84*a2d5ed94SMarcin Wojtas #define TPM_CC_HashSequenceStart		0x00000186
85*a2d5ed94SMarcin Wojtas 
86*a2d5ed94SMarcin Wojtas /* Timeout before data in read buffer is discarded */
87*a2d5ed94SMarcin Wojtas #define	TPM_READ_TIMEOUT	500000
88*a2d5ed94SMarcin Wojtas 
89*a2d5ed94SMarcin Wojtas #define	TPM_BUFSIZE		0x1000
90*a2d5ed94SMarcin Wojtas 
91*a2d5ed94SMarcin Wojtas #define	TPM_HEADER_SIZE		10
92*a2d5ed94SMarcin Wojtas 
93*a2d5ed94SMarcin Wojtas #define	TPM_CDEV_NAME		"tpm0"
94*a2d5ed94SMarcin Wojtas #define	TPM_CDEV_PERM_FLAG	0600
95*a2d5ed94SMarcin Wojtas 
96*a2d5ed94SMarcin Wojtas struct tpm_sc {
97*a2d5ed94SMarcin Wojtas 	device_t	dev;
98*a2d5ed94SMarcin Wojtas 
99*a2d5ed94SMarcin Wojtas 	struct resource	*mem_res;
100*a2d5ed94SMarcin Wojtas 	struct resource	*irq_res;
101*a2d5ed94SMarcin Wojtas 	int		mem_rid;
102*a2d5ed94SMarcin Wojtas 	int		irq_rid;
103*a2d5ed94SMarcin Wojtas 
104*a2d5ed94SMarcin Wojtas 	struct cdev	*sc_cdev;
105*a2d5ed94SMarcin Wojtas 
106*a2d5ed94SMarcin Wojtas 	struct sx 	dev_lock;
107*a2d5ed94SMarcin Wojtas 	struct cv	buf_cv;
108*a2d5ed94SMarcin Wojtas 
109*a2d5ed94SMarcin Wojtas 	void 		*intr_cookie;
110*a2d5ed94SMarcin Wojtas 	int 		intr_type;	/* Current event type */
111*a2d5ed94SMarcin Wojtas 	bool 		interrupts;
112*a2d5ed94SMarcin Wojtas 
113*a2d5ed94SMarcin Wojtas 	uint8_t 	*buf;
114*a2d5ed94SMarcin Wojtas 	size_t		pending_data_length;
115*a2d5ed94SMarcin Wojtas 
116*a2d5ed94SMarcin Wojtas 	struct callout 	discard_buffer_callout;
117*a2d5ed94SMarcin Wojtas 
118*a2d5ed94SMarcin Wojtas 	int		(*transmit)(struct tpm_sc *, size_t);
119*a2d5ed94SMarcin Wojtas };
120*a2d5ed94SMarcin Wojtas 
121*a2d5ed94SMarcin Wojtas int tpm20_suspend(device_t dev);
122*a2d5ed94SMarcin Wojtas int tpm20_shutdown(device_t dev);
123*a2d5ed94SMarcin Wojtas int32_t tpm20_get_timeout(uint32_t command);
124*a2d5ed94SMarcin Wojtas int tpm20_init(struct tpm_sc *sc);
125*a2d5ed94SMarcin Wojtas void tpm20_release(struct tpm_sc *sc);
126*a2d5ed94SMarcin Wojtas 
127*a2d5ed94SMarcin Wojtas d_open_t	tpm20_open;
128*a2d5ed94SMarcin Wojtas d_close_t	tpm20_close;
129*a2d5ed94SMarcin Wojtas d_read_t	tpm20_read;
130*a2d5ed94SMarcin Wojtas d_write_t	tpm20_write;
131*a2d5ed94SMarcin Wojtas d_ioctl_t	tpm20_ioctl;
132*a2d5ed94SMarcin Wojtas 
133*a2d5ed94SMarcin Wojtas static struct cdevsw tpm_cdevsw = {
134*a2d5ed94SMarcin Wojtas 	.d_version = D_VERSION,
135*a2d5ed94SMarcin Wojtas 	.d_open = tpm20_open,
136*a2d5ed94SMarcin Wojtas 	.d_close = tpm20_close,
137*a2d5ed94SMarcin Wojtas 	.d_read = tpm20_read,
138*a2d5ed94SMarcin Wojtas 	.d_write = tpm20_write,
139*a2d5ed94SMarcin Wojtas 	.d_ioctl = tpm20_ioctl,
140*a2d5ed94SMarcin Wojtas 	.d_name = "tpm20",
141*a2d5ed94SMarcin Wojtas };
142*a2d5ed94SMarcin Wojtas 
143*a2d5ed94SMarcin Wojtas /* Small helper routines for io ops */
144*a2d5ed94SMarcin Wojtas static inline uint8_t
145*a2d5ed94SMarcin Wojtas RD1(struct tpm_sc *sc, bus_size_t off)
146*a2d5ed94SMarcin Wojtas {
147*a2d5ed94SMarcin Wojtas 
148*a2d5ed94SMarcin Wojtas 	return (bus_read_1(sc->mem_res, off));
149*a2d5ed94SMarcin Wojtas }
150*a2d5ed94SMarcin Wojtas static inline uint32_t
151*a2d5ed94SMarcin Wojtas RD4(struct tpm_sc *sc, bus_size_t off)
152*a2d5ed94SMarcin Wojtas {
153*a2d5ed94SMarcin Wojtas 
154*a2d5ed94SMarcin Wojtas 	return (bus_read_4(sc->mem_res, off));
155*a2d5ed94SMarcin Wojtas }
156*a2d5ed94SMarcin Wojtas static inline uint64_t
157*a2d5ed94SMarcin Wojtas RD8(struct tpm_sc *sc, bus_size_t off)
158*a2d5ed94SMarcin Wojtas {
159*a2d5ed94SMarcin Wojtas 
160*a2d5ed94SMarcin Wojtas 	return (bus_read_8(sc->mem_res, off));
161*a2d5ed94SMarcin Wojtas }
162*a2d5ed94SMarcin Wojtas static inline void
163*a2d5ed94SMarcin Wojtas WR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
164*a2d5ed94SMarcin Wojtas {
165*a2d5ed94SMarcin Wojtas 
166*a2d5ed94SMarcin Wojtas 	bus_write_1(sc->mem_res, off, val);
167*a2d5ed94SMarcin Wojtas }
168*a2d5ed94SMarcin Wojtas static inline void
169*a2d5ed94SMarcin Wojtas WR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
170*a2d5ed94SMarcin Wojtas {
171*a2d5ed94SMarcin Wojtas 
172*a2d5ed94SMarcin Wojtas 	bus_write_4(sc->mem_res, off, val);
173*a2d5ed94SMarcin Wojtas }
174*a2d5ed94SMarcin Wojtas static inline void
175*a2d5ed94SMarcin Wojtas AND4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
176*a2d5ed94SMarcin Wojtas {
177*a2d5ed94SMarcin Wojtas 
178*a2d5ed94SMarcin Wojtas 	WR4(sc, off, RD4(sc, off) & val);
179*a2d5ed94SMarcin Wojtas }
180*a2d5ed94SMarcin Wojtas static inline void
181*a2d5ed94SMarcin Wojtas OR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
182*a2d5ed94SMarcin Wojtas {
183*a2d5ed94SMarcin Wojtas 
184*a2d5ed94SMarcin Wojtas 	WR1(sc, off, RD1(sc, off) | val);
185*a2d5ed94SMarcin Wojtas }
186*a2d5ed94SMarcin Wojtas static inline void
187*a2d5ed94SMarcin Wojtas OR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
188*a2d5ed94SMarcin Wojtas {
189*a2d5ed94SMarcin Wojtas 
190*a2d5ed94SMarcin Wojtas 	WR4(sc, off, RD4(sc, off) | val);
191*a2d5ed94SMarcin Wojtas }
192*a2d5ed94SMarcin Wojtas #endif	/* _TPM20_H_ */
193