1342084Smw/*-
2342084Smw * Copyright (c) 2018 Stormshield.
3342084Smw * Copyright (c) 2018 Semihalf.
4342084Smw * All rights reserved.
5342084Smw *
6342084Smw * Redistribution and use in source and binary forms, with or without
7342084Smw * modification, are permitted provided that the following conditions
8342084Smw * are met:
9342084Smw * 1. Redistributions of source code must retain the above copyright
10342084Smw *    notice, this list of conditions and the following disclaimer.
11342084Smw * 2. Redistributions in binary form must reproduce the above copyright
12342084Smw *    notice, this list of conditions and the following disclaimer in the
13342084Smw *    documentation and/or other materials provided with the distribution.
14342084Smw *
15342084Smw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16342084Smw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17342084Smw * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18342084Smw * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19342084Smw * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20342084Smw * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21342084Smw * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22342084Smw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23342084Smw * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24342084Smw * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25342084Smw * POSSIBILITY OF SUCH DAMAGE.
26342084Smw */
27342084Smw
28342084Smw#ifndef _TPM20_H_
29346725Smw#define	_TPM20_H_
30342084Smw
31342084Smw#include <sys/cdefs.h>
32342084Smw__FBSDID("$FreeBSD: stable/11/sys/dev/tpm/tpm20.h 346725 2019-04-26 01:58:36Z mw $");
33342084Smw
34342084Smw#include <sys/endian.h>
35342084Smw#include <sys/param.h>
36342084Smw#include <sys/kernel.h>
37342084Smw#include <sys/malloc.h>
38342084Smw#include <sys/proc.h>
39342084Smw#include <sys/systm.h>
40342084Smw
41342084Smw#include <sys/bus.h>
42342084Smw#include <sys/callout.h>
43342084Smw#include <sys/conf.h>
44342084Smw#include <sys/module.h>
45342084Smw#include <sys/rman.h>
46342084Smw#include <sys/sx.h>
47342084Smw#include <sys/uio.h>
48342084Smw
49342084Smw#include <machine/bus.h>
50342084Smw#include <machine/md_var.h>
51342084Smw#include <machine/resource.h>
52342084Smw
53342084Smw#include <contrib/dev/acpica/include/acpi.h>
54342084Smw#include <contrib/dev/acpica/include/accommon.h>
55342084Smw#include <dev/acpica/acpivar.h>
56342084Smw#include "opt_acpi.h"
57342084Smw
58346725Smw#include "opt_tpm.h"
59346725Smw
60342084Smw#define	BIT(x) (1 << (x))
61342084Smw
62342084Smw/* Timeouts in us */
63346725Smw#define	TPM_TIMEOUT_A			750000
64346725Smw#define	TPM_TIMEOUT_B			2000000
65346725Smw#define	TPM_TIMEOUT_C			200000
66346725Smw#define	TPM_TIMEOUT_D			30000
67342084Smw
68342084Smw/*
69342084Smw * Generating RSA key pair takes ~(10-20s), which is significantly longer than
70342084Smw * any timeout defined in spec. Because of that we need a new one.
71342084Smw */
72346725Smw#define	TPM_TIMEOUT_LONG		40000000
73342084Smw
74342084Smw/* List of commands that require TPM_TIMEOUT_LONG time to complete */
75346725Smw#define	TPM_CC_CreatePrimary		0x00000131
76342084Smw#define	TPM_CC_Create			0x00000153
77342084Smw#define	TPM_CC_CreateLoaded		0x00000191
78342084Smw
79342084Smw/* List of commands that require only TPM_TIMEOUT_C time to complete */
80346725Smw#define	TPM_CC_SequenceComplete		0x0000013e
81346725Smw#define	TPM_CC_Startup			0x00000144
82346725Smw#define	TPM_CC_SequenceUpdate		0x0000015c
83346725Smw#define	TPM_CC_GetCapability		0x0000017a
84346725Smw#define	TPM_CC_PCR_Extend		0x00000182
85346725Smw#define	TPM_CC_EventSequenceComplete	0x00000185
86346725Smw#define	TPM_CC_HashSequenceStart	0x00000186
87342084Smw
88342084Smw/* Timeout before data in read buffer is discarded */
89346725Smw#define	TPM_READ_TIMEOUT		500000
90342084Smw
91346725Smw#define	TPM_BUFSIZE			0x1000
92342084Smw
93346725Smw#define	TPM_HEADER_SIZE			10
94342084Smw
95346725Smw#define	TPM_CDEV_NAME			"tpm0"
96346725Smw#define	TPM_CDEV_PERM_FLAG		0600
97342084Smw
98346722Smw
99346725Smw#define	TPM2_START_METHOD_ACPI		2
100346725Smw#define	TPM2_START_METHOD_TIS		6
101346725Smw#define	TPM2_START_METHOD_CRB		7
102346725Smw#define	TPM2_START_METHOD_CRB_ACPI	8
103346722Smw
104342084Smwstruct tpm_sc {
105342084Smw	device_t	dev;
106342084Smw
107342084Smw	struct resource	*mem_res;
108342084Smw	struct resource	*irq_res;
109342084Smw	int		mem_rid;
110342084Smw	int		irq_rid;
111342084Smw
112342084Smw	struct cdev	*sc_cdev;
113342084Smw
114342084Smw	struct sx 	dev_lock;
115342084Smw	struct cv	buf_cv;
116342084Smw
117342084Smw	void 		*intr_cookie;
118342084Smw	int 		intr_type;	/* Current event type */
119342084Smw	bool 		interrupts;
120342084Smw
121342084Smw	uint8_t 	*buf;
122342084Smw	size_t		pending_data_length;
123346725Smw	lwpid_t		owner_tid;
124342084Smw
125342084Smw	struct callout 	discard_buffer_callout;
126346725Smw#ifdef TPM_HARVEST
127346725Smw	struct callout 	harvest_callout;
128346725Smw	int		harvest_ticks;
129346725Smw#endif
130342084Smw
131342084Smw	int		(*transmit)(struct tpm_sc *, size_t);
132342084Smw};
133342084Smw
134342084Smwint tpm20_suspend(device_t dev);
135342084Smwint tpm20_shutdown(device_t dev);
136342084Smwint32_t tpm20_get_timeout(uint32_t command);
137342084Smwint tpm20_init(struct tpm_sc *sc);
138342084Smwvoid tpm20_release(struct tpm_sc *sc);
139342084Smw
140342084Smw/* Small helper routines for io ops */
141342084Smwstatic inline uint8_t
142342084SmwRD1(struct tpm_sc *sc, bus_size_t off)
143342084Smw{
144342084Smw
145342084Smw	return (bus_read_1(sc->mem_res, off));
146342084Smw}
147342084Smwstatic inline uint32_t
148342084SmwRD4(struct tpm_sc *sc, bus_size_t off)
149342084Smw{
150342084Smw
151342084Smw	return (bus_read_4(sc->mem_res, off));
152342084Smw}
153346721Smw#ifdef __amd64__
154342084Smwstatic inline uint64_t
155342084SmwRD8(struct tpm_sc *sc, bus_size_t off)
156342084Smw{
157342084Smw
158342084Smw	return (bus_read_8(sc->mem_res, off));
159342084Smw}
160346721Smw#endif
161342084Smwstatic inline void
162342084SmwWR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
163342084Smw{
164342084Smw
165342084Smw	bus_write_1(sc->mem_res, off, val);
166342084Smw}
167342084Smwstatic inline void
168342084SmwWR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
169342084Smw{
170342084Smw
171342084Smw	bus_write_4(sc->mem_res, off, val);
172342084Smw}
173342084Smwstatic inline void
174342084SmwAND4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
175342084Smw{
176342084Smw
177342084Smw	WR4(sc, off, RD4(sc, off) & val);
178342084Smw}
179342084Smwstatic inline void
180342084SmwOR1(struct tpm_sc *sc, bus_size_t off, uint8_t val)
181342084Smw{
182342084Smw
183342084Smw	WR1(sc, off, RD1(sc, off) | val);
184342084Smw}
185342084Smwstatic inline void
186342084SmwOR4(struct tpm_sc *sc, bus_size_t off, uint32_t val)
187342084Smw{
188342084Smw
189342084Smw	WR4(sc, off, RD4(sc, off) | val);
190342084Smw}
191342084Smw#endif	/* _TPM20_H_ */
192