xref: /openbmc/linux/drivers/char/tpm/tpm-interface.c (revision 9deb0eb7cad450cd942a0eca11a198f6d24cb3d4)
1*9deb0eb7SJason Gunthorpe /*
2*9deb0eb7SJason Gunthorpe  * Copyright (C) 2004 IBM Corporation
3*9deb0eb7SJason Gunthorpe  *
4*9deb0eb7SJason Gunthorpe  * Authors:
5*9deb0eb7SJason Gunthorpe  * Leendert van Doorn <leendert@watson.ibm.com>
6*9deb0eb7SJason Gunthorpe  * Dave Safford <safford@watson.ibm.com>
7*9deb0eb7SJason Gunthorpe  * Reiner Sailer <sailer@watson.ibm.com>
8*9deb0eb7SJason Gunthorpe  * Kylene Hall <kjhall@us.ibm.com>
9*9deb0eb7SJason Gunthorpe  *
10*9deb0eb7SJason Gunthorpe  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
11*9deb0eb7SJason Gunthorpe  *
12*9deb0eb7SJason Gunthorpe  * Device driver for TCG/TCPA TPM (trusted platform module).
13*9deb0eb7SJason Gunthorpe  * Specifications at www.trustedcomputinggroup.org
14*9deb0eb7SJason Gunthorpe  *
15*9deb0eb7SJason Gunthorpe  * This program is free software; you can redistribute it and/or
16*9deb0eb7SJason Gunthorpe  * modify it under the terms of the GNU General Public License as
17*9deb0eb7SJason Gunthorpe  * published by the Free Software Foundation, version 2 of the
18*9deb0eb7SJason Gunthorpe  * License.
19*9deb0eb7SJason Gunthorpe  *
20*9deb0eb7SJason Gunthorpe  * Note, the TPM chip is not interrupt driven (only polling)
21*9deb0eb7SJason Gunthorpe  * and can have very long timeouts (minutes!). Hence the unusual
22*9deb0eb7SJason Gunthorpe  * calls to msleep.
23*9deb0eb7SJason Gunthorpe  *
24*9deb0eb7SJason Gunthorpe  */
25*9deb0eb7SJason Gunthorpe 
26*9deb0eb7SJason Gunthorpe #include <linux/poll.h>
27*9deb0eb7SJason Gunthorpe #include <linux/slab.h>
28*9deb0eb7SJason Gunthorpe #include <linux/mutex.h>
29*9deb0eb7SJason Gunthorpe #include <linux/spinlock.h>
30*9deb0eb7SJason Gunthorpe #include <linux/freezer.h>
31*9deb0eb7SJason Gunthorpe 
32*9deb0eb7SJason Gunthorpe #include "tpm.h"
33*9deb0eb7SJason Gunthorpe #include "tpm_eventlog.h"
34*9deb0eb7SJason Gunthorpe 
35*9deb0eb7SJason Gunthorpe enum tpm_duration {
36*9deb0eb7SJason Gunthorpe 	TPM_SHORT = 0,
37*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM = 1,
38*9deb0eb7SJason Gunthorpe 	TPM_LONG = 2,
39*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
40*9deb0eb7SJason Gunthorpe };
41*9deb0eb7SJason Gunthorpe 
42*9deb0eb7SJason Gunthorpe #define TPM_MAX_ORDINAL 243
43*9deb0eb7SJason Gunthorpe #define TSC_MAX_ORDINAL 12
44*9deb0eb7SJason Gunthorpe #define TPM_PROTECTED_COMMAND 0x00
45*9deb0eb7SJason Gunthorpe #define TPM_CONNECTION_COMMAND 0x40
46*9deb0eb7SJason Gunthorpe 
47*9deb0eb7SJason Gunthorpe /*
48*9deb0eb7SJason Gunthorpe  * Bug workaround - some TPM's don't flush the most
49*9deb0eb7SJason Gunthorpe  * recently changed pcr on suspend, so force the flush
50*9deb0eb7SJason Gunthorpe  * with an extend to the selected _unused_ non-volatile pcr.
51*9deb0eb7SJason Gunthorpe  */
52*9deb0eb7SJason Gunthorpe static int tpm_suspend_pcr;
53*9deb0eb7SJason Gunthorpe module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
54*9deb0eb7SJason Gunthorpe MODULE_PARM_DESC(suspend_pcr,
55*9deb0eb7SJason Gunthorpe 		 "PCR to use for dummy writes to faciltate flush on suspend.");
56*9deb0eb7SJason Gunthorpe 
57*9deb0eb7SJason Gunthorpe static LIST_HEAD(tpm_chip_list);
58*9deb0eb7SJason Gunthorpe static DEFINE_SPINLOCK(driver_lock);
59*9deb0eb7SJason Gunthorpe static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
60*9deb0eb7SJason Gunthorpe 
61*9deb0eb7SJason Gunthorpe /*
62*9deb0eb7SJason Gunthorpe  * Array with one entry per ordinal defining the maximum amount
63*9deb0eb7SJason Gunthorpe  * of time the chip could take to return the result.  The ordinal
64*9deb0eb7SJason Gunthorpe  * designation of short, medium or long is defined in a table in
65*9deb0eb7SJason Gunthorpe  * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
66*9deb0eb7SJason Gunthorpe  * values of the SHORT, MEDIUM, and LONG durations are retrieved
67*9deb0eb7SJason Gunthorpe  * from the chip during initialization with a call to tpm_get_timeouts.
68*9deb0eb7SJason Gunthorpe  */
69*9deb0eb7SJason Gunthorpe static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
70*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 0 */
71*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
72*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
73*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
74*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
75*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 5 */
76*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
77*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
78*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
79*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
80*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 10 */
81*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
82*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
83*9deb0eb7SJason Gunthorpe 	TPM_LONG,
84*9deb0eb7SJason Gunthorpe 	TPM_LONG,
85*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 15 */
86*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
87*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
88*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
89*9deb0eb7SJason Gunthorpe 	TPM_LONG,
90*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 20 */
91*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
92*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
93*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
94*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
95*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 25 */
96*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
97*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
98*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
99*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
100*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 30 */
101*9deb0eb7SJason Gunthorpe 	TPM_LONG,
102*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
103*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
104*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
105*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 35 */
106*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
107*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
108*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
109*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
110*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 40 */
111*9deb0eb7SJason Gunthorpe 	TPM_LONG,
112*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
113*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
114*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
115*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 45 */
116*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
117*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
118*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
119*9deb0eb7SJason Gunthorpe 	TPM_LONG,
120*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 50 */
121*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
122*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
123*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
124*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
125*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 55 */
126*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
127*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
128*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
129*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
130*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 60 */
131*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
132*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
133*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
134*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
135*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 65 */
136*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
137*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
138*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
139*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
140*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 70 */
141*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
142*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
143*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
144*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
145*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 75 */
146*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
147*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
148*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
149*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
150*9deb0eb7SJason Gunthorpe 	TPM_LONG,		/* 80 */
151*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
152*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
153*9deb0eb7SJason Gunthorpe 	TPM_LONG,
154*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
155*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 85 */
156*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
157*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
158*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
159*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
160*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 90 */
161*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
162*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
163*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
164*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
165*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 95 */
166*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
167*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
168*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
169*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
170*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 100 */
171*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
172*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
173*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
174*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
175*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 105 */
176*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
177*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
178*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
179*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
180*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 110 */
181*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
182*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
183*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
184*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
185*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 115 */
186*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
187*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
188*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
189*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
190*9deb0eb7SJason Gunthorpe 	TPM_LONG,		/* 120 */
191*9deb0eb7SJason Gunthorpe 	TPM_LONG,
192*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
193*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
194*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
195*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 125 */
196*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
197*9deb0eb7SJason Gunthorpe 	TPM_LONG,
198*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
199*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
200*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 130 */
201*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
202*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
203*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
204*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
205*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 135 */
206*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
207*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
208*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
209*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
210*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 140 */
211*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
212*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
213*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
214*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
215*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 145 */
216*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
217*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
218*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
219*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
220*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 150 */
221*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
222*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
223*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
224*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
225*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 155 */
226*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
227*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
228*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
229*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
230*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 160 */
231*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
232*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
233*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
234*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
235*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 165 */
236*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
237*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
238*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
239*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
240*9deb0eb7SJason Gunthorpe 	TPM_LONG,		/* 170 */
241*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
242*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
243*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
244*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
245*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 175 */
246*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
247*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
248*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
249*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
250*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 180 */
251*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
252*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
253*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
254*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
255*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 185 */
256*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
257*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
258*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
259*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
260*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 190 */
261*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
262*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
263*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
264*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
265*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 195 */
266*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
267*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
268*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
269*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
270*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 200 */
271*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
272*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
273*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
274*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
275*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 205 */
276*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
277*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
278*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
279*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
280*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,		/* 210 */
281*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
282*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
283*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
284*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
285*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 215 */
286*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
287*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
288*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
289*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
290*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 220 */
291*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
292*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
293*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
294*9deb0eb7SJason Gunthorpe 	TPM_SHORT,
295*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 225 */
296*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
297*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
298*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
299*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
300*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 230 */
301*9deb0eb7SJason Gunthorpe 	TPM_LONG,
302*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
303*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
304*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
305*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,		/* 235 */
306*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
307*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
308*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
309*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
310*9deb0eb7SJason Gunthorpe 	TPM_SHORT,		/* 240 */
311*9deb0eb7SJason Gunthorpe 	TPM_UNDEFINED,
312*9deb0eb7SJason Gunthorpe 	TPM_MEDIUM,
313*9deb0eb7SJason Gunthorpe };
314*9deb0eb7SJason Gunthorpe 
315*9deb0eb7SJason Gunthorpe static void user_reader_timeout(unsigned long ptr)
316*9deb0eb7SJason Gunthorpe {
317*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = (struct tpm_chip *) ptr;
318*9deb0eb7SJason Gunthorpe 
319*9deb0eb7SJason Gunthorpe 	schedule_work(&chip->work);
320*9deb0eb7SJason Gunthorpe }
321*9deb0eb7SJason Gunthorpe 
322*9deb0eb7SJason Gunthorpe static void timeout_work(struct work_struct *work)
323*9deb0eb7SJason Gunthorpe {
324*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = container_of(work, struct tpm_chip, work);
325*9deb0eb7SJason Gunthorpe 
326*9deb0eb7SJason Gunthorpe 	mutex_lock(&chip->buffer_mutex);
327*9deb0eb7SJason Gunthorpe 	atomic_set(&chip->data_pending, 0);
328*9deb0eb7SJason Gunthorpe 	memset(chip->data_buffer, 0, TPM_BUFSIZE);
329*9deb0eb7SJason Gunthorpe 	mutex_unlock(&chip->buffer_mutex);
330*9deb0eb7SJason Gunthorpe }
331*9deb0eb7SJason Gunthorpe 
332*9deb0eb7SJason Gunthorpe /*
333*9deb0eb7SJason Gunthorpe  * Returns max number of jiffies to wait
334*9deb0eb7SJason Gunthorpe  */
335*9deb0eb7SJason Gunthorpe unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
336*9deb0eb7SJason Gunthorpe 					   u32 ordinal)
337*9deb0eb7SJason Gunthorpe {
338*9deb0eb7SJason Gunthorpe 	int duration_idx = TPM_UNDEFINED;
339*9deb0eb7SJason Gunthorpe 	int duration = 0;
340*9deb0eb7SJason Gunthorpe 	u8 category = (ordinal >> 24) & 0xFF;
341*9deb0eb7SJason Gunthorpe 
342*9deb0eb7SJason Gunthorpe 	if ((category == TPM_PROTECTED_COMMAND && ordinal < TPM_MAX_ORDINAL) ||
343*9deb0eb7SJason Gunthorpe 	    (category == TPM_CONNECTION_COMMAND && ordinal < TSC_MAX_ORDINAL))
344*9deb0eb7SJason Gunthorpe 		duration_idx = tpm_ordinal_duration[ordinal];
345*9deb0eb7SJason Gunthorpe 
346*9deb0eb7SJason Gunthorpe 	if (duration_idx != TPM_UNDEFINED)
347*9deb0eb7SJason Gunthorpe 		duration = chip->vendor.duration[duration_idx];
348*9deb0eb7SJason Gunthorpe 	if (duration <= 0)
349*9deb0eb7SJason Gunthorpe 		return 2 * 60 * HZ;
350*9deb0eb7SJason Gunthorpe 	else
351*9deb0eb7SJason Gunthorpe 		return duration;
352*9deb0eb7SJason Gunthorpe }
353*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
354*9deb0eb7SJason Gunthorpe 
355*9deb0eb7SJason Gunthorpe /*
356*9deb0eb7SJason Gunthorpe  * Internal kernel interface to transmit TPM commands
357*9deb0eb7SJason Gunthorpe  */
358*9deb0eb7SJason Gunthorpe static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
359*9deb0eb7SJason Gunthorpe 			    size_t bufsiz)
360*9deb0eb7SJason Gunthorpe {
361*9deb0eb7SJason Gunthorpe 	ssize_t rc;
362*9deb0eb7SJason Gunthorpe 	u32 count, ordinal;
363*9deb0eb7SJason Gunthorpe 	unsigned long stop;
364*9deb0eb7SJason Gunthorpe 
365*9deb0eb7SJason Gunthorpe 	if (bufsiz > TPM_BUFSIZE)
366*9deb0eb7SJason Gunthorpe 		bufsiz = TPM_BUFSIZE;
367*9deb0eb7SJason Gunthorpe 
368*9deb0eb7SJason Gunthorpe 	count = be32_to_cpu(*((__be32 *) (buf + 2)));
369*9deb0eb7SJason Gunthorpe 	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
370*9deb0eb7SJason Gunthorpe 	if (count == 0)
371*9deb0eb7SJason Gunthorpe 		return -ENODATA;
372*9deb0eb7SJason Gunthorpe 	if (count > bufsiz) {
373*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
374*9deb0eb7SJason Gunthorpe 			"invalid count value %x %zx\n", count, bufsiz);
375*9deb0eb7SJason Gunthorpe 		return -E2BIG;
376*9deb0eb7SJason Gunthorpe 	}
377*9deb0eb7SJason Gunthorpe 
378*9deb0eb7SJason Gunthorpe 	mutex_lock(&chip->tpm_mutex);
379*9deb0eb7SJason Gunthorpe 
380*9deb0eb7SJason Gunthorpe 	rc = chip->vendor.send(chip, (u8 *) buf, count);
381*9deb0eb7SJason Gunthorpe 	if (rc < 0) {
382*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
383*9deb0eb7SJason Gunthorpe 			"tpm_transmit: tpm_send: error %zd\n", rc);
384*9deb0eb7SJason Gunthorpe 		goto out;
385*9deb0eb7SJason Gunthorpe 	}
386*9deb0eb7SJason Gunthorpe 
387*9deb0eb7SJason Gunthorpe 	if (chip->vendor.irq)
388*9deb0eb7SJason Gunthorpe 		goto out_recv;
389*9deb0eb7SJason Gunthorpe 
390*9deb0eb7SJason Gunthorpe 	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
391*9deb0eb7SJason Gunthorpe 	do {
392*9deb0eb7SJason Gunthorpe 		u8 status = chip->vendor.status(chip);
393*9deb0eb7SJason Gunthorpe 		if ((status & chip->vendor.req_complete_mask) ==
394*9deb0eb7SJason Gunthorpe 		    chip->vendor.req_complete_val)
395*9deb0eb7SJason Gunthorpe 			goto out_recv;
396*9deb0eb7SJason Gunthorpe 
397*9deb0eb7SJason Gunthorpe 		if (chip->vendor.req_canceled(chip, status)) {
398*9deb0eb7SJason Gunthorpe 			dev_err(chip->dev, "Operation Canceled\n");
399*9deb0eb7SJason Gunthorpe 			rc = -ECANCELED;
400*9deb0eb7SJason Gunthorpe 			goto out;
401*9deb0eb7SJason Gunthorpe 		}
402*9deb0eb7SJason Gunthorpe 
403*9deb0eb7SJason Gunthorpe 		msleep(TPM_TIMEOUT);	/* CHECK */
404*9deb0eb7SJason Gunthorpe 		rmb();
405*9deb0eb7SJason Gunthorpe 	} while (time_before(jiffies, stop));
406*9deb0eb7SJason Gunthorpe 
407*9deb0eb7SJason Gunthorpe 	chip->vendor.cancel(chip);
408*9deb0eb7SJason Gunthorpe 	dev_err(chip->dev, "Operation Timed out\n");
409*9deb0eb7SJason Gunthorpe 	rc = -ETIME;
410*9deb0eb7SJason Gunthorpe 	goto out;
411*9deb0eb7SJason Gunthorpe 
412*9deb0eb7SJason Gunthorpe out_recv:
413*9deb0eb7SJason Gunthorpe 	rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
414*9deb0eb7SJason Gunthorpe 	if (rc < 0)
415*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
416*9deb0eb7SJason Gunthorpe 			"tpm_transmit: tpm_recv: error %zd\n", rc);
417*9deb0eb7SJason Gunthorpe out:
418*9deb0eb7SJason Gunthorpe 	mutex_unlock(&chip->tpm_mutex);
419*9deb0eb7SJason Gunthorpe 	return rc;
420*9deb0eb7SJason Gunthorpe }
421*9deb0eb7SJason Gunthorpe 
422*9deb0eb7SJason Gunthorpe #define TPM_DIGEST_SIZE 20
423*9deb0eb7SJason Gunthorpe #define TPM_RET_CODE_IDX 6
424*9deb0eb7SJason Gunthorpe 
425*9deb0eb7SJason Gunthorpe enum tpm_capabilities {
426*9deb0eb7SJason Gunthorpe 	TPM_CAP_FLAG = cpu_to_be32(4),
427*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP = cpu_to_be32(5),
428*9deb0eb7SJason Gunthorpe 	CAP_VERSION_1_1 = cpu_to_be32(0x06),
429*9deb0eb7SJason Gunthorpe 	CAP_VERSION_1_2 = cpu_to_be32(0x1A)
430*9deb0eb7SJason Gunthorpe };
431*9deb0eb7SJason Gunthorpe 
432*9deb0eb7SJason Gunthorpe enum tpm_sub_capabilities {
433*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP_PCR = cpu_to_be32(0x101),
434*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103),
435*9deb0eb7SJason Gunthorpe 	TPM_CAP_FLAG_PERM = cpu_to_be32(0x108),
436*9deb0eb7SJason Gunthorpe 	TPM_CAP_FLAG_VOL = cpu_to_be32(0x109),
437*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP_OWNER = cpu_to_be32(0x111),
438*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
439*9deb0eb7SJason Gunthorpe 	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
440*9deb0eb7SJason Gunthorpe 
441*9deb0eb7SJason Gunthorpe };
442*9deb0eb7SJason Gunthorpe 
443*9deb0eb7SJason Gunthorpe static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
444*9deb0eb7SJason Gunthorpe 			    int len, const char *desc)
445*9deb0eb7SJason Gunthorpe {
446*9deb0eb7SJason Gunthorpe 	int err;
447*9deb0eb7SJason Gunthorpe 
448*9deb0eb7SJason Gunthorpe 	len = tpm_transmit(chip, (u8 *) cmd, len);
449*9deb0eb7SJason Gunthorpe 	if (len <  0)
450*9deb0eb7SJason Gunthorpe 		return len;
451*9deb0eb7SJason Gunthorpe 	else if (len < TPM_HEADER_SIZE)
452*9deb0eb7SJason Gunthorpe 		return -EFAULT;
453*9deb0eb7SJason Gunthorpe 
454*9deb0eb7SJason Gunthorpe 	err = be32_to_cpu(cmd->header.out.return_code);
455*9deb0eb7SJason Gunthorpe 	if (err != 0 && desc)
456*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
457*9deb0eb7SJason Gunthorpe 
458*9deb0eb7SJason Gunthorpe 	return err;
459*9deb0eb7SJason Gunthorpe }
460*9deb0eb7SJason Gunthorpe 
461*9deb0eb7SJason Gunthorpe #define TPM_INTERNAL_RESULT_SIZE 200
462*9deb0eb7SJason Gunthorpe #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
463*9deb0eb7SJason Gunthorpe #define TPM_ORD_GET_CAP cpu_to_be32(101)
464*9deb0eb7SJason Gunthorpe #define TPM_ORD_GET_RANDOM cpu_to_be32(70)
465*9deb0eb7SJason Gunthorpe 
466*9deb0eb7SJason Gunthorpe static const struct tpm_input_header tpm_getcap_header = {
467*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
468*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(22),
469*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_GET_CAP
470*9deb0eb7SJason Gunthorpe };
471*9deb0eb7SJason Gunthorpe 
472*9deb0eb7SJason Gunthorpe ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
473*9deb0eb7SJason Gunthorpe 		   const char *desc)
474*9deb0eb7SJason Gunthorpe {
475*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t tpm_cmd;
476*9deb0eb7SJason Gunthorpe 	int rc;
477*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
478*9deb0eb7SJason Gunthorpe 
479*9deb0eb7SJason Gunthorpe 	tpm_cmd.header.in = tpm_getcap_header;
480*9deb0eb7SJason Gunthorpe 	if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
481*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.cap = subcap_id;
482*9deb0eb7SJason Gunthorpe 		/*subcap field not necessary */
483*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
484*9deb0eb7SJason Gunthorpe 		tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32));
485*9deb0eb7SJason Gunthorpe 	} else {
486*9deb0eb7SJason Gunthorpe 		if (subcap_id == TPM_CAP_FLAG_PERM ||
487*9deb0eb7SJason Gunthorpe 		    subcap_id == TPM_CAP_FLAG_VOL)
488*9deb0eb7SJason Gunthorpe 			tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
489*9deb0eb7SJason Gunthorpe 		else
490*9deb0eb7SJason Gunthorpe 			tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
491*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
492*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.subcap = subcap_id;
493*9deb0eb7SJason Gunthorpe 	}
494*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc);
495*9deb0eb7SJason Gunthorpe 	if (!rc)
496*9deb0eb7SJason Gunthorpe 		*cap = tpm_cmd.params.getcap_out.cap;
497*9deb0eb7SJason Gunthorpe 	return rc;
498*9deb0eb7SJason Gunthorpe }
499*9deb0eb7SJason Gunthorpe 
500*9deb0eb7SJason Gunthorpe void tpm_gen_interrupt(struct tpm_chip *chip)
501*9deb0eb7SJason Gunthorpe {
502*9deb0eb7SJason Gunthorpe 	struct	tpm_cmd_t tpm_cmd;
503*9deb0eb7SJason Gunthorpe 	ssize_t rc;
504*9deb0eb7SJason Gunthorpe 
505*9deb0eb7SJason Gunthorpe 	tpm_cmd.header.in = tpm_getcap_header;
506*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
507*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
508*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
509*9deb0eb7SJason Gunthorpe 
510*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
511*9deb0eb7SJason Gunthorpe 			"attempting to determine the timeouts");
512*9deb0eb7SJason Gunthorpe }
513*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
514*9deb0eb7SJason Gunthorpe 
515*9deb0eb7SJason Gunthorpe #define TPM_ORD_STARTUP cpu_to_be32(153)
516*9deb0eb7SJason Gunthorpe #define TPM_ST_CLEAR cpu_to_be16(1)
517*9deb0eb7SJason Gunthorpe #define TPM_ST_STATE cpu_to_be16(2)
518*9deb0eb7SJason Gunthorpe #define TPM_ST_DEACTIVATED cpu_to_be16(3)
519*9deb0eb7SJason Gunthorpe static const struct tpm_input_header tpm_startup_header = {
520*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
521*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(12),
522*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_STARTUP
523*9deb0eb7SJason Gunthorpe };
524*9deb0eb7SJason Gunthorpe 
525*9deb0eb7SJason Gunthorpe static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
526*9deb0eb7SJason Gunthorpe {
527*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t start_cmd;
528*9deb0eb7SJason Gunthorpe 	start_cmd.header.in = tpm_startup_header;
529*9deb0eb7SJason Gunthorpe 	start_cmd.params.startup_in.startup_type = startup_type;
530*9deb0eb7SJason Gunthorpe 	return transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
531*9deb0eb7SJason Gunthorpe 			    "attempting to start the TPM");
532*9deb0eb7SJason Gunthorpe }
533*9deb0eb7SJason Gunthorpe 
534*9deb0eb7SJason Gunthorpe int tpm_get_timeouts(struct tpm_chip *chip)
535*9deb0eb7SJason Gunthorpe {
536*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t tpm_cmd;
537*9deb0eb7SJason Gunthorpe 	struct timeout_t *timeout_cap;
538*9deb0eb7SJason Gunthorpe 	struct duration_t *duration_cap;
539*9deb0eb7SJason Gunthorpe 	ssize_t rc;
540*9deb0eb7SJason Gunthorpe 	u32 timeout;
541*9deb0eb7SJason Gunthorpe 	unsigned int scale = 1;
542*9deb0eb7SJason Gunthorpe 
543*9deb0eb7SJason Gunthorpe 	tpm_cmd.header.in = tpm_getcap_header;
544*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
545*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
546*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
547*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL);
548*9deb0eb7SJason Gunthorpe 
549*9deb0eb7SJason Gunthorpe 	if (rc == TPM_ERR_INVALID_POSTINIT) {
550*9deb0eb7SJason Gunthorpe 		/* The TPM is not started, we are the first to talk to it.
551*9deb0eb7SJason Gunthorpe 		   Execute a startup command. */
552*9deb0eb7SJason Gunthorpe 		dev_info(chip->dev, "Issuing TPM_STARTUP");
553*9deb0eb7SJason Gunthorpe 		if (tpm_startup(chip, TPM_ST_CLEAR))
554*9deb0eb7SJason Gunthorpe 			return rc;
555*9deb0eb7SJason Gunthorpe 
556*9deb0eb7SJason Gunthorpe 		tpm_cmd.header.in = tpm_getcap_header;
557*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
558*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
559*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
560*9deb0eb7SJason Gunthorpe 		rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
561*9deb0eb7SJason Gunthorpe 				  NULL);
562*9deb0eb7SJason Gunthorpe 	}
563*9deb0eb7SJason Gunthorpe 	if (rc) {
564*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
565*9deb0eb7SJason Gunthorpe 			"A TPM error (%zd) occurred attempting to determine the timeouts\n",
566*9deb0eb7SJason Gunthorpe 			rc);
567*9deb0eb7SJason Gunthorpe 		goto duration;
568*9deb0eb7SJason Gunthorpe 	}
569*9deb0eb7SJason Gunthorpe 
570*9deb0eb7SJason Gunthorpe 	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
571*9deb0eb7SJason Gunthorpe 	    be32_to_cpu(tpm_cmd.header.out.length)
572*9deb0eb7SJason Gunthorpe 	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
573*9deb0eb7SJason Gunthorpe 		return -EINVAL;
574*9deb0eb7SJason Gunthorpe 
575*9deb0eb7SJason Gunthorpe 	timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
576*9deb0eb7SJason Gunthorpe 	/* Don't overwrite default if value is 0 */
577*9deb0eb7SJason Gunthorpe 	timeout = be32_to_cpu(timeout_cap->a);
578*9deb0eb7SJason Gunthorpe 	if (timeout && timeout < 1000) {
579*9deb0eb7SJason Gunthorpe 		/* timeouts in msec rather usec */
580*9deb0eb7SJason Gunthorpe 		scale = 1000;
581*9deb0eb7SJason Gunthorpe 		chip->vendor.timeout_adjusted = true;
582*9deb0eb7SJason Gunthorpe 	}
583*9deb0eb7SJason Gunthorpe 	if (timeout)
584*9deb0eb7SJason Gunthorpe 		chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
585*9deb0eb7SJason Gunthorpe 	timeout = be32_to_cpu(timeout_cap->b);
586*9deb0eb7SJason Gunthorpe 	if (timeout)
587*9deb0eb7SJason Gunthorpe 		chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
588*9deb0eb7SJason Gunthorpe 	timeout = be32_to_cpu(timeout_cap->c);
589*9deb0eb7SJason Gunthorpe 	if (timeout)
590*9deb0eb7SJason Gunthorpe 		chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
591*9deb0eb7SJason Gunthorpe 	timeout = be32_to_cpu(timeout_cap->d);
592*9deb0eb7SJason Gunthorpe 	if (timeout)
593*9deb0eb7SJason Gunthorpe 		chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
594*9deb0eb7SJason Gunthorpe 
595*9deb0eb7SJason Gunthorpe duration:
596*9deb0eb7SJason Gunthorpe 	tpm_cmd.header.in = tpm_getcap_header;
597*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
598*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
599*9deb0eb7SJason Gunthorpe 	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
600*9deb0eb7SJason Gunthorpe 
601*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
602*9deb0eb7SJason Gunthorpe 			"attempting to determine the durations");
603*9deb0eb7SJason Gunthorpe 	if (rc)
604*9deb0eb7SJason Gunthorpe 		return rc;
605*9deb0eb7SJason Gunthorpe 
606*9deb0eb7SJason Gunthorpe 	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
607*9deb0eb7SJason Gunthorpe 	    be32_to_cpu(tpm_cmd.header.out.length)
608*9deb0eb7SJason Gunthorpe 	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
609*9deb0eb7SJason Gunthorpe 		return -EINVAL;
610*9deb0eb7SJason Gunthorpe 
611*9deb0eb7SJason Gunthorpe 	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
612*9deb0eb7SJason Gunthorpe 	chip->vendor.duration[TPM_SHORT] =
613*9deb0eb7SJason Gunthorpe 	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
614*9deb0eb7SJason Gunthorpe 	chip->vendor.duration[TPM_MEDIUM] =
615*9deb0eb7SJason Gunthorpe 	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
616*9deb0eb7SJason Gunthorpe 	chip->vendor.duration[TPM_LONG] =
617*9deb0eb7SJason Gunthorpe 	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
618*9deb0eb7SJason Gunthorpe 
619*9deb0eb7SJason Gunthorpe 	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
620*9deb0eb7SJason Gunthorpe 	 * value wrong and apparently reports msecs rather than usecs. So we
621*9deb0eb7SJason Gunthorpe 	 * fix up the resulting too-small TPM_SHORT value to make things work.
622*9deb0eb7SJason Gunthorpe 	 * We also scale the TPM_MEDIUM and -_LONG values by 1000.
623*9deb0eb7SJason Gunthorpe 	 */
624*9deb0eb7SJason Gunthorpe 	if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
625*9deb0eb7SJason Gunthorpe 		chip->vendor.duration[TPM_SHORT] = HZ;
626*9deb0eb7SJason Gunthorpe 		chip->vendor.duration[TPM_MEDIUM] *= 1000;
627*9deb0eb7SJason Gunthorpe 		chip->vendor.duration[TPM_LONG] *= 1000;
628*9deb0eb7SJason Gunthorpe 		chip->vendor.duration_adjusted = true;
629*9deb0eb7SJason Gunthorpe 		dev_info(chip->dev, "Adjusting TPM timeout parameters.");
630*9deb0eb7SJason Gunthorpe 	}
631*9deb0eb7SJason Gunthorpe 	return 0;
632*9deb0eb7SJason Gunthorpe }
633*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_get_timeouts);
634*9deb0eb7SJason Gunthorpe 
635*9deb0eb7SJason Gunthorpe #define TPM_ORD_CONTINUE_SELFTEST 83
636*9deb0eb7SJason Gunthorpe #define CONTINUE_SELFTEST_RESULT_SIZE 10
637*9deb0eb7SJason Gunthorpe 
638*9deb0eb7SJason Gunthorpe static struct tpm_input_header continue_selftest_header = {
639*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
640*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(10),
641*9deb0eb7SJason Gunthorpe 	.ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
642*9deb0eb7SJason Gunthorpe };
643*9deb0eb7SJason Gunthorpe 
644*9deb0eb7SJason Gunthorpe /**
645*9deb0eb7SJason Gunthorpe  * tpm_continue_selftest -- run TPM's selftest
646*9deb0eb7SJason Gunthorpe  * @chip: TPM chip to use
647*9deb0eb7SJason Gunthorpe  *
648*9deb0eb7SJason Gunthorpe  * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
649*9deb0eb7SJason Gunthorpe  * a TPM error code.
650*9deb0eb7SJason Gunthorpe  */
651*9deb0eb7SJason Gunthorpe static int tpm_continue_selftest(struct tpm_chip *chip)
652*9deb0eb7SJason Gunthorpe {
653*9deb0eb7SJason Gunthorpe 	int rc;
654*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t cmd;
655*9deb0eb7SJason Gunthorpe 
656*9deb0eb7SJason Gunthorpe 	cmd.header.in = continue_selftest_header;
657*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
658*9deb0eb7SJason Gunthorpe 			  "continue selftest");
659*9deb0eb7SJason Gunthorpe 	return rc;
660*9deb0eb7SJason Gunthorpe }
661*9deb0eb7SJason Gunthorpe 
662*9deb0eb7SJason Gunthorpe ssize_t tpm_show_enabled(struct device *dev, struct device_attribute *attr,
663*9deb0eb7SJason Gunthorpe 			char *buf)
664*9deb0eb7SJason Gunthorpe {
665*9deb0eb7SJason Gunthorpe 	cap_t cap;
666*9deb0eb7SJason Gunthorpe 	ssize_t rc;
667*9deb0eb7SJason Gunthorpe 
668*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
669*9deb0eb7SJason Gunthorpe 			 "attempting to determine the permanent enabled state");
670*9deb0eb7SJason Gunthorpe 	if (rc)
671*9deb0eb7SJason Gunthorpe 		return 0;
672*9deb0eb7SJason Gunthorpe 
673*9deb0eb7SJason Gunthorpe 	rc = sprintf(buf, "%d\n", !cap.perm_flags.disable);
674*9deb0eb7SJason Gunthorpe 	return rc;
675*9deb0eb7SJason Gunthorpe }
676*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_enabled);
677*9deb0eb7SJason Gunthorpe 
678*9deb0eb7SJason Gunthorpe ssize_t tpm_show_active(struct device *dev, struct device_attribute *attr,
679*9deb0eb7SJason Gunthorpe 			char *buf)
680*9deb0eb7SJason Gunthorpe {
681*9deb0eb7SJason Gunthorpe 	cap_t cap;
682*9deb0eb7SJason Gunthorpe 	ssize_t rc;
683*9deb0eb7SJason Gunthorpe 
684*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
685*9deb0eb7SJason Gunthorpe 			 "attempting to determine the permanent active state");
686*9deb0eb7SJason Gunthorpe 	if (rc)
687*9deb0eb7SJason Gunthorpe 		return 0;
688*9deb0eb7SJason Gunthorpe 
689*9deb0eb7SJason Gunthorpe 	rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated);
690*9deb0eb7SJason Gunthorpe 	return rc;
691*9deb0eb7SJason Gunthorpe }
692*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_active);
693*9deb0eb7SJason Gunthorpe 
694*9deb0eb7SJason Gunthorpe ssize_t tpm_show_owned(struct device *dev, struct device_attribute *attr,
695*9deb0eb7SJason Gunthorpe 			char *buf)
696*9deb0eb7SJason Gunthorpe {
697*9deb0eb7SJason Gunthorpe 	cap_t cap;
698*9deb0eb7SJason Gunthorpe 	ssize_t rc;
699*9deb0eb7SJason Gunthorpe 
700*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap,
701*9deb0eb7SJason Gunthorpe 			 "attempting to determine the owner state");
702*9deb0eb7SJason Gunthorpe 	if (rc)
703*9deb0eb7SJason Gunthorpe 		return 0;
704*9deb0eb7SJason Gunthorpe 
705*9deb0eb7SJason Gunthorpe 	rc = sprintf(buf, "%d\n", cap.owned);
706*9deb0eb7SJason Gunthorpe 	return rc;
707*9deb0eb7SJason Gunthorpe }
708*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_owned);
709*9deb0eb7SJason Gunthorpe 
710*9deb0eb7SJason Gunthorpe ssize_t tpm_show_temp_deactivated(struct device *dev,
711*9deb0eb7SJason Gunthorpe 				struct device_attribute *attr, char *buf)
712*9deb0eb7SJason Gunthorpe {
713*9deb0eb7SJason Gunthorpe 	cap_t cap;
714*9deb0eb7SJason Gunthorpe 	ssize_t rc;
715*9deb0eb7SJason Gunthorpe 
716*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap,
717*9deb0eb7SJason Gunthorpe 			 "attempting to determine the temporary state");
718*9deb0eb7SJason Gunthorpe 	if (rc)
719*9deb0eb7SJason Gunthorpe 		return 0;
720*9deb0eb7SJason Gunthorpe 
721*9deb0eb7SJason Gunthorpe 	rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated);
722*9deb0eb7SJason Gunthorpe 	return rc;
723*9deb0eb7SJason Gunthorpe }
724*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
725*9deb0eb7SJason Gunthorpe 
726*9deb0eb7SJason Gunthorpe /*
727*9deb0eb7SJason Gunthorpe  * tpm_chip_find_get - return tpm_chip for given chip number
728*9deb0eb7SJason Gunthorpe  */
729*9deb0eb7SJason Gunthorpe static struct tpm_chip *tpm_chip_find_get(int chip_num)
730*9deb0eb7SJason Gunthorpe {
731*9deb0eb7SJason Gunthorpe 	struct tpm_chip *pos, *chip = NULL;
732*9deb0eb7SJason Gunthorpe 
733*9deb0eb7SJason Gunthorpe 	rcu_read_lock();
734*9deb0eb7SJason Gunthorpe 	list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
735*9deb0eb7SJason Gunthorpe 		if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
736*9deb0eb7SJason Gunthorpe 			continue;
737*9deb0eb7SJason Gunthorpe 
738*9deb0eb7SJason Gunthorpe 		if (try_module_get(pos->dev->driver->owner)) {
739*9deb0eb7SJason Gunthorpe 			chip = pos;
740*9deb0eb7SJason Gunthorpe 			break;
741*9deb0eb7SJason Gunthorpe 		}
742*9deb0eb7SJason Gunthorpe 	}
743*9deb0eb7SJason Gunthorpe 	rcu_read_unlock();
744*9deb0eb7SJason Gunthorpe 	return chip;
745*9deb0eb7SJason Gunthorpe }
746*9deb0eb7SJason Gunthorpe 
747*9deb0eb7SJason Gunthorpe #define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
748*9deb0eb7SJason Gunthorpe #define READ_PCR_RESULT_SIZE 30
749*9deb0eb7SJason Gunthorpe static struct tpm_input_header pcrread_header = {
750*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
751*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(14),
752*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORDINAL_PCRREAD
753*9deb0eb7SJason Gunthorpe };
754*9deb0eb7SJason Gunthorpe 
755*9deb0eb7SJason Gunthorpe static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
756*9deb0eb7SJason Gunthorpe {
757*9deb0eb7SJason Gunthorpe 	int rc;
758*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t cmd;
759*9deb0eb7SJason Gunthorpe 
760*9deb0eb7SJason Gunthorpe 	cmd.header.in = pcrread_header;
761*9deb0eb7SJason Gunthorpe 	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
762*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
763*9deb0eb7SJason Gunthorpe 			  "attempting to read a pcr value");
764*9deb0eb7SJason Gunthorpe 
765*9deb0eb7SJason Gunthorpe 	if (rc == 0)
766*9deb0eb7SJason Gunthorpe 		memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
767*9deb0eb7SJason Gunthorpe 		       TPM_DIGEST_SIZE);
768*9deb0eb7SJason Gunthorpe 	return rc;
769*9deb0eb7SJason Gunthorpe }
770*9deb0eb7SJason Gunthorpe 
771*9deb0eb7SJason Gunthorpe /**
772*9deb0eb7SJason Gunthorpe  * tpm_pcr_read - read a pcr value
773*9deb0eb7SJason Gunthorpe  * @chip_num:	tpm idx # or ANY
774*9deb0eb7SJason Gunthorpe  * @pcr_idx:	pcr idx to retrieve
775*9deb0eb7SJason Gunthorpe  * @res_buf:	TPM_PCR value
776*9deb0eb7SJason Gunthorpe  *		size of res_buf is 20 bytes (or NULL if you don't care)
777*9deb0eb7SJason Gunthorpe  *
778*9deb0eb7SJason Gunthorpe  * The TPM driver should be built-in, but for whatever reason it
779*9deb0eb7SJason Gunthorpe  * isn't, protect against the chip disappearing, by incrementing
780*9deb0eb7SJason Gunthorpe  * the module usage count.
781*9deb0eb7SJason Gunthorpe  */
782*9deb0eb7SJason Gunthorpe int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
783*9deb0eb7SJason Gunthorpe {
784*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip;
785*9deb0eb7SJason Gunthorpe 	int rc;
786*9deb0eb7SJason Gunthorpe 
787*9deb0eb7SJason Gunthorpe 	chip = tpm_chip_find_get(chip_num);
788*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
789*9deb0eb7SJason Gunthorpe 		return -ENODEV;
790*9deb0eb7SJason Gunthorpe 	rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
791*9deb0eb7SJason Gunthorpe 	tpm_chip_put(chip);
792*9deb0eb7SJason Gunthorpe 	return rc;
793*9deb0eb7SJason Gunthorpe }
794*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pcr_read);
795*9deb0eb7SJason Gunthorpe 
796*9deb0eb7SJason Gunthorpe /**
797*9deb0eb7SJason Gunthorpe  * tpm_pcr_extend - extend pcr value with hash
798*9deb0eb7SJason Gunthorpe  * @chip_num:	tpm idx # or AN&
799*9deb0eb7SJason Gunthorpe  * @pcr_idx:	pcr idx to extend
800*9deb0eb7SJason Gunthorpe  * @hash:	hash value used to extend pcr value
801*9deb0eb7SJason Gunthorpe  *
802*9deb0eb7SJason Gunthorpe  * The TPM driver should be built-in, but for whatever reason it
803*9deb0eb7SJason Gunthorpe  * isn't, protect against the chip disappearing, by incrementing
804*9deb0eb7SJason Gunthorpe  * the module usage count.
805*9deb0eb7SJason Gunthorpe  */
806*9deb0eb7SJason Gunthorpe #define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
807*9deb0eb7SJason Gunthorpe #define EXTEND_PCR_RESULT_SIZE 34
808*9deb0eb7SJason Gunthorpe static struct tpm_input_header pcrextend_header = {
809*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
810*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(34),
811*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_PCR_EXTEND
812*9deb0eb7SJason Gunthorpe };
813*9deb0eb7SJason Gunthorpe 
814*9deb0eb7SJason Gunthorpe int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
815*9deb0eb7SJason Gunthorpe {
816*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t cmd;
817*9deb0eb7SJason Gunthorpe 	int rc;
818*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip;
819*9deb0eb7SJason Gunthorpe 
820*9deb0eb7SJason Gunthorpe 	chip = tpm_chip_find_get(chip_num);
821*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
822*9deb0eb7SJason Gunthorpe 		return -ENODEV;
823*9deb0eb7SJason Gunthorpe 
824*9deb0eb7SJason Gunthorpe 	cmd.header.in = pcrextend_header;
825*9deb0eb7SJason Gunthorpe 	cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
826*9deb0eb7SJason Gunthorpe 	memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
827*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
828*9deb0eb7SJason Gunthorpe 			  "attempting extend a PCR value");
829*9deb0eb7SJason Gunthorpe 
830*9deb0eb7SJason Gunthorpe 	tpm_chip_put(chip);
831*9deb0eb7SJason Gunthorpe 	return rc;
832*9deb0eb7SJason Gunthorpe }
833*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pcr_extend);
834*9deb0eb7SJason Gunthorpe 
835*9deb0eb7SJason Gunthorpe /**
836*9deb0eb7SJason Gunthorpe  * tpm_do_selftest - have the TPM continue its selftest and wait until it
837*9deb0eb7SJason Gunthorpe  *                   can receive further commands
838*9deb0eb7SJason Gunthorpe  * @chip: TPM chip to use
839*9deb0eb7SJason Gunthorpe  *
840*9deb0eb7SJason Gunthorpe  * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
841*9deb0eb7SJason Gunthorpe  * a TPM error code.
842*9deb0eb7SJason Gunthorpe  */
843*9deb0eb7SJason Gunthorpe int tpm_do_selftest(struct tpm_chip *chip)
844*9deb0eb7SJason Gunthorpe {
845*9deb0eb7SJason Gunthorpe 	int rc;
846*9deb0eb7SJason Gunthorpe 	unsigned int loops;
847*9deb0eb7SJason Gunthorpe 	unsigned int delay_msec = 100;
848*9deb0eb7SJason Gunthorpe 	unsigned long duration;
849*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t cmd;
850*9deb0eb7SJason Gunthorpe 
851*9deb0eb7SJason Gunthorpe 	duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);
852*9deb0eb7SJason Gunthorpe 
853*9deb0eb7SJason Gunthorpe 	loops = jiffies_to_msecs(duration) / delay_msec;
854*9deb0eb7SJason Gunthorpe 
855*9deb0eb7SJason Gunthorpe 	rc = tpm_continue_selftest(chip);
856*9deb0eb7SJason Gunthorpe 	/* This may fail if there was no TPM driver during a suspend/resume
857*9deb0eb7SJason Gunthorpe 	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
858*9deb0eb7SJason Gunthorpe 	 */
859*9deb0eb7SJason Gunthorpe 	if (rc)
860*9deb0eb7SJason Gunthorpe 		return rc;
861*9deb0eb7SJason Gunthorpe 
862*9deb0eb7SJason Gunthorpe 	do {
863*9deb0eb7SJason Gunthorpe 		/* Attempt to read a PCR value */
864*9deb0eb7SJason Gunthorpe 		cmd.header.in = pcrread_header;
865*9deb0eb7SJason Gunthorpe 		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
866*9deb0eb7SJason Gunthorpe 		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
867*9deb0eb7SJason Gunthorpe 		/* Some buggy TPMs will not respond to tpm_tis_ready() for
868*9deb0eb7SJason Gunthorpe 		 * around 300ms while the self test is ongoing, keep trying
869*9deb0eb7SJason Gunthorpe 		 * until the self test duration expires. */
870*9deb0eb7SJason Gunthorpe 		if (rc == -ETIME) {
871*9deb0eb7SJason Gunthorpe 			dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test");
872*9deb0eb7SJason Gunthorpe 			msleep(delay_msec);
873*9deb0eb7SJason Gunthorpe 			continue;
874*9deb0eb7SJason Gunthorpe 		}
875*9deb0eb7SJason Gunthorpe 
876*9deb0eb7SJason Gunthorpe 		if (rc < TPM_HEADER_SIZE)
877*9deb0eb7SJason Gunthorpe 			return -EFAULT;
878*9deb0eb7SJason Gunthorpe 
879*9deb0eb7SJason Gunthorpe 		rc = be32_to_cpu(cmd.header.out.return_code);
880*9deb0eb7SJason Gunthorpe 		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
881*9deb0eb7SJason Gunthorpe 			dev_info(chip->dev,
882*9deb0eb7SJason Gunthorpe 				 "TPM is disabled/deactivated (0x%X)\n", rc);
883*9deb0eb7SJason Gunthorpe 			/* TPM is disabled and/or deactivated; driver can
884*9deb0eb7SJason Gunthorpe 			 * proceed and TPM does handle commands for
885*9deb0eb7SJason Gunthorpe 			 * suspend/resume correctly
886*9deb0eb7SJason Gunthorpe 			 */
887*9deb0eb7SJason Gunthorpe 			return 0;
888*9deb0eb7SJason Gunthorpe 		}
889*9deb0eb7SJason Gunthorpe 		if (rc != TPM_WARN_DOING_SELFTEST)
890*9deb0eb7SJason Gunthorpe 			return rc;
891*9deb0eb7SJason Gunthorpe 		msleep(delay_msec);
892*9deb0eb7SJason Gunthorpe 	} while (--loops > 0);
893*9deb0eb7SJason Gunthorpe 
894*9deb0eb7SJason Gunthorpe 	return rc;
895*9deb0eb7SJason Gunthorpe }
896*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_do_selftest);
897*9deb0eb7SJason Gunthorpe 
898*9deb0eb7SJason Gunthorpe int tpm_send(u32 chip_num, void *cmd, size_t buflen)
899*9deb0eb7SJason Gunthorpe {
900*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip;
901*9deb0eb7SJason Gunthorpe 	int rc;
902*9deb0eb7SJason Gunthorpe 
903*9deb0eb7SJason Gunthorpe 	chip = tpm_chip_find_get(chip_num);
904*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
905*9deb0eb7SJason Gunthorpe 		return -ENODEV;
906*9deb0eb7SJason Gunthorpe 
907*9deb0eb7SJason Gunthorpe 	rc = transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
908*9deb0eb7SJason Gunthorpe 
909*9deb0eb7SJason Gunthorpe 	tpm_chip_put(chip);
910*9deb0eb7SJason Gunthorpe 	return rc;
911*9deb0eb7SJason Gunthorpe }
912*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_send);
913*9deb0eb7SJason Gunthorpe 
914*9deb0eb7SJason Gunthorpe ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
915*9deb0eb7SJason Gunthorpe 		      char *buf)
916*9deb0eb7SJason Gunthorpe {
917*9deb0eb7SJason Gunthorpe 	cap_t cap;
918*9deb0eb7SJason Gunthorpe 	u8 digest[TPM_DIGEST_SIZE];
919*9deb0eb7SJason Gunthorpe 	ssize_t rc;
920*9deb0eb7SJason Gunthorpe 	int i, j, num_pcrs;
921*9deb0eb7SJason Gunthorpe 	char *str = buf;
922*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
923*9deb0eb7SJason Gunthorpe 
924*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
925*9deb0eb7SJason Gunthorpe 			"attempting to determine the number of PCRS");
926*9deb0eb7SJason Gunthorpe 	if (rc)
927*9deb0eb7SJason Gunthorpe 		return 0;
928*9deb0eb7SJason Gunthorpe 
929*9deb0eb7SJason Gunthorpe 	num_pcrs = be32_to_cpu(cap.num_pcrs);
930*9deb0eb7SJason Gunthorpe 	for (i = 0; i < num_pcrs; i++) {
931*9deb0eb7SJason Gunthorpe 		rc = __tpm_pcr_read(chip, i, digest);
932*9deb0eb7SJason Gunthorpe 		if (rc)
933*9deb0eb7SJason Gunthorpe 			break;
934*9deb0eb7SJason Gunthorpe 		str += sprintf(str, "PCR-%02d: ", i);
935*9deb0eb7SJason Gunthorpe 		for (j = 0; j < TPM_DIGEST_SIZE; j++)
936*9deb0eb7SJason Gunthorpe 			str += sprintf(str, "%02X ", digest[j]);
937*9deb0eb7SJason Gunthorpe 		str += sprintf(str, "\n");
938*9deb0eb7SJason Gunthorpe 	}
939*9deb0eb7SJason Gunthorpe 	return str - buf;
940*9deb0eb7SJason Gunthorpe }
941*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_pcrs);
942*9deb0eb7SJason Gunthorpe 
943*9deb0eb7SJason Gunthorpe #define  READ_PUBEK_RESULT_SIZE 314
944*9deb0eb7SJason Gunthorpe #define TPM_ORD_READPUBEK cpu_to_be32(124)
945*9deb0eb7SJason Gunthorpe static struct tpm_input_header tpm_readpubek_header = {
946*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
947*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(30),
948*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_READPUBEK
949*9deb0eb7SJason Gunthorpe };
950*9deb0eb7SJason Gunthorpe 
951*9deb0eb7SJason Gunthorpe ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
952*9deb0eb7SJason Gunthorpe 		       char *buf)
953*9deb0eb7SJason Gunthorpe {
954*9deb0eb7SJason Gunthorpe 	u8 *data;
955*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t tpm_cmd;
956*9deb0eb7SJason Gunthorpe 	ssize_t err;
957*9deb0eb7SJason Gunthorpe 	int i, rc;
958*9deb0eb7SJason Gunthorpe 	char *str = buf;
959*9deb0eb7SJason Gunthorpe 
960*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
961*9deb0eb7SJason Gunthorpe 
962*9deb0eb7SJason Gunthorpe 	tpm_cmd.header.in = tpm_readpubek_header;
963*9deb0eb7SJason Gunthorpe 	err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
964*9deb0eb7SJason Gunthorpe 			"attempting to read the PUBEK");
965*9deb0eb7SJason Gunthorpe 	if (err)
966*9deb0eb7SJason Gunthorpe 		goto out;
967*9deb0eb7SJason Gunthorpe 
968*9deb0eb7SJason Gunthorpe 	/*
969*9deb0eb7SJason Gunthorpe 	   ignore header 10 bytes
970*9deb0eb7SJason Gunthorpe 	   algorithm 32 bits (1 == RSA )
971*9deb0eb7SJason Gunthorpe 	   encscheme 16 bits
972*9deb0eb7SJason Gunthorpe 	   sigscheme 16 bits
973*9deb0eb7SJason Gunthorpe 	   parameters (RSA 12->bytes: keybit, #primes, expbit)
974*9deb0eb7SJason Gunthorpe 	   keylenbytes 32 bits
975*9deb0eb7SJason Gunthorpe 	   256 byte modulus
976*9deb0eb7SJason Gunthorpe 	   ignore checksum 20 bytes
977*9deb0eb7SJason Gunthorpe 	 */
978*9deb0eb7SJason Gunthorpe 	data = tpm_cmd.params.readpubek_out_buffer;
979*9deb0eb7SJason Gunthorpe 	str +=
980*9deb0eb7SJason Gunthorpe 	    sprintf(str,
981*9deb0eb7SJason Gunthorpe 		    "Algorithm: %02X %02X %02X %02X\n"
982*9deb0eb7SJason Gunthorpe 		    "Encscheme: %02X %02X\n"
983*9deb0eb7SJason Gunthorpe 		    "Sigscheme: %02X %02X\n"
984*9deb0eb7SJason Gunthorpe 		    "Parameters: %02X %02X %02X %02X "
985*9deb0eb7SJason Gunthorpe 		    "%02X %02X %02X %02X "
986*9deb0eb7SJason Gunthorpe 		    "%02X %02X %02X %02X\n"
987*9deb0eb7SJason Gunthorpe 		    "Modulus length: %d\n"
988*9deb0eb7SJason Gunthorpe 		    "Modulus:\n",
989*9deb0eb7SJason Gunthorpe 		    data[0], data[1], data[2], data[3],
990*9deb0eb7SJason Gunthorpe 		    data[4], data[5],
991*9deb0eb7SJason Gunthorpe 		    data[6], data[7],
992*9deb0eb7SJason Gunthorpe 		    data[12], data[13], data[14], data[15],
993*9deb0eb7SJason Gunthorpe 		    data[16], data[17], data[18], data[19],
994*9deb0eb7SJason Gunthorpe 		    data[20], data[21], data[22], data[23],
995*9deb0eb7SJason Gunthorpe 		    be32_to_cpu(*((__be32 *) (data + 24))));
996*9deb0eb7SJason Gunthorpe 
997*9deb0eb7SJason Gunthorpe 	for (i = 0; i < 256; i++) {
998*9deb0eb7SJason Gunthorpe 		str += sprintf(str, "%02X ", data[i + 28]);
999*9deb0eb7SJason Gunthorpe 		if ((i + 1) % 16 == 0)
1000*9deb0eb7SJason Gunthorpe 			str += sprintf(str, "\n");
1001*9deb0eb7SJason Gunthorpe 	}
1002*9deb0eb7SJason Gunthorpe out:
1003*9deb0eb7SJason Gunthorpe 	rc = str - buf;
1004*9deb0eb7SJason Gunthorpe 	return rc;
1005*9deb0eb7SJason Gunthorpe }
1006*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_pubek);
1007*9deb0eb7SJason Gunthorpe 
1008*9deb0eb7SJason Gunthorpe 
1009*9deb0eb7SJason Gunthorpe ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
1010*9deb0eb7SJason Gunthorpe 		      char *buf)
1011*9deb0eb7SJason Gunthorpe {
1012*9deb0eb7SJason Gunthorpe 	cap_t cap;
1013*9deb0eb7SJason Gunthorpe 	ssize_t rc;
1014*9deb0eb7SJason Gunthorpe 	char *str = buf;
1015*9deb0eb7SJason Gunthorpe 
1016*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
1017*9deb0eb7SJason Gunthorpe 			"attempting to determine the manufacturer");
1018*9deb0eb7SJason Gunthorpe 	if (rc)
1019*9deb0eb7SJason Gunthorpe 		return 0;
1020*9deb0eb7SJason Gunthorpe 	str += sprintf(str, "Manufacturer: 0x%x\n",
1021*9deb0eb7SJason Gunthorpe 		       be32_to_cpu(cap.manufacturer_id));
1022*9deb0eb7SJason Gunthorpe 
1023*9deb0eb7SJason Gunthorpe 	/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
1024*9deb0eb7SJason Gunthorpe 	rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
1025*9deb0eb7SJason Gunthorpe 			 "attempting to determine the 1.2 version");
1026*9deb0eb7SJason Gunthorpe 	if (!rc) {
1027*9deb0eb7SJason Gunthorpe 		str += sprintf(str,
1028*9deb0eb7SJason Gunthorpe 			       "TCG version: %d.%d\nFirmware version: %d.%d\n",
1029*9deb0eb7SJason Gunthorpe 			       cap.tpm_version_1_2.Major,
1030*9deb0eb7SJason Gunthorpe 			       cap.tpm_version_1_2.Minor,
1031*9deb0eb7SJason Gunthorpe 			       cap.tpm_version_1_2.revMajor,
1032*9deb0eb7SJason Gunthorpe 			       cap.tpm_version_1_2.revMinor);
1033*9deb0eb7SJason Gunthorpe 	} else {
1034*9deb0eb7SJason Gunthorpe 		/* Otherwise just use TPM_STRUCT_VER */
1035*9deb0eb7SJason Gunthorpe 		rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
1036*9deb0eb7SJason Gunthorpe 				"attempting to determine the 1.1 version");
1037*9deb0eb7SJason Gunthorpe 		if (rc)
1038*9deb0eb7SJason Gunthorpe 			return 0;
1039*9deb0eb7SJason Gunthorpe 		str += sprintf(str,
1040*9deb0eb7SJason Gunthorpe 			       "TCG version: %d.%d\nFirmware version: %d.%d\n",
1041*9deb0eb7SJason Gunthorpe 			       cap.tpm_version.Major,
1042*9deb0eb7SJason Gunthorpe 			       cap.tpm_version.Minor,
1043*9deb0eb7SJason Gunthorpe 			       cap.tpm_version.revMajor,
1044*9deb0eb7SJason Gunthorpe 			       cap.tpm_version.revMinor);
1045*9deb0eb7SJason Gunthorpe 	}
1046*9deb0eb7SJason Gunthorpe 
1047*9deb0eb7SJason Gunthorpe 	return str - buf;
1048*9deb0eb7SJason Gunthorpe }
1049*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_caps);
1050*9deb0eb7SJason Gunthorpe 
1051*9deb0eb7SJason Gunthorpe ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
1052*9deb0eb7SJason Gunthorpe 			  char *buf)
1053*9deb0eb7SJason Gunthorpe {
1054*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1055*9deb0eb7SJason Gunthorpe 
1056*9deb0eb7SJason Gunthorpe 	if (chip->vendor.duration[TPM_LONG] == 0)
1057*9deb0eb7SJason Gunthorpe 		return 0;
1058*9deb0eb7SJason Gunthorpe 
1059*9deb0eb7SJason Gunthorpe 	return sprintf(buf, "%d %d %d [%s]\n",
1060*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
1061*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
1062*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
1063*9deb0eb7SJason Gunthorpe 		       chip->vendor.duration_adjusted
1064*9deb0eb7SJason Gunthorpe 		       ? "adjusted" : "original");
1065*9deb0eb7SJason Gunthorpe }
1066*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_durations);
1067*9deb0eb7SJason Gunthorpe 
1068*9deb0eb7SJason Gunthorpe ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
1069*9deb0eb7SJason Gunthorpe 			  char *buf)
1070*9deb0eb7SJason Gunthorpe {
1071*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1072*9deb0eb7SJason Gunthorpe 
1073*9deb0eb7SJason Gunthorpe 	return sprintf(buf, "%d %d %d %d [%s]\n",
1074*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.timeout_a),
1075*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.timeout_b),
1076*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.timeout_c),
1077*9deb0eb7SJason Gunthorpe 		       jiffies_to_usecs(chip->vendor.timeout_d),
1078*9deb0eb7SJason Gunthorpe 		       chip->vendor.timeout_adjusted
1079*9deb0eb7SJason Gunthorpe 		       ? "adjusted" : "original");
1080*9deb0eb7SJason Gunthorpe }
1081*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_show_timeouts);
1082*9deb0eb7SJason Gunthorpe 
1083*9deb0eb7SJason Gunthorpe ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
1084*9deb0eb7SJason Gunthorpe 			const char *buf, size_t count)
1085*9deb0eb7SJason Gunthorpe {
1086*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1087*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
1088*9deb0eb7SJason Gunthorpe 		return 0;
1089*9deb0eb7SJason Gunthorpe 
1090*9deb0eb7SJason Gunthorpe 	chip->vendor.cancel(chip);
1091*9deb0eb7SJason Gunthorpe 	return count;
1092*9deb0eb7SJason Gunthorpe }
1093*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_store_cancel);
1094*9deb0eb7SJason Gunthorpe 
1095*9deb0eb7SJason Gunthorpe static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
1096*9deb0eb7SJason Gunthorpe 					bool check_cancel, bool *canceled)
1097*9deb0eb7SJason Gunthorpe {
1098*9deb0eb7SJason Gunthorpe 	u8 status = chip->vendor.status(chip);
1099*9deb0eb7SJason Gunthorpe 
1100*9deb0eb7SJason Gunthorpe 	*canceled = false;
1101*9deb0eb7SJason Gunthorpe 	if ((status & mask) == mask)
1102*9deb0eb7SJason Gunthorpe 		return true;
1103*9deb0eb7SJason Gunthorpe 	if (check_cancel && chip->vendor.req_canceled(chip, status)) {
1104*9deb0eb7SJason Gunthorpe 		*canceled = true;
1105*9deb0eb7SJason Gunthorpe 		return true;
1106*9deb0eb7SJason Gunthorpe 	}
1107*9deb0eb7SJason Gunthorpe 	return false;
1108*9deb0eb7SJason Gunthorpe }
1109*9deb0eb7SJason Gunthorpe 
1110*9deb0eb7SJason Gunthorpe int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
1111*9deb0eb7SJason Gunthorpe 		      wait_queue_head_t *queue, bool check_cancel)
1112*9deb0eb7SJason Gunthorpe {
1113*9deb0eb7SJason Gunthorpe 	unsigned long stop;
1114*9deb0eb7SJason Gunthorpe 	long rc;
1115*9deb0eb7SJason Gunthorpe 	u8 status;
1116*9deb0eb7SJason Gunthorpe 	bool canceled = false;
1117*9deb0eb7SJason Gunthorpe 
1118*9deb0eb7SJason Gunthorpe 	/* check current status */
1119*9deb0eb7SJason Gunthorpe 	status = chip->vendor.status(chip);
1120*9deb0eb7SJason Gunthorpe 	if ((status & mask) == mask)
1121*9deb0eb7SJason Gunthorpe 		return 0;
1122*9deb0eb7SJason Gunthorpe 
1123*9deb0eb7SJason Gunthorpe 	stop = jiffies + timeout;
1124*9deb0eb7SJason Gunthorpe 
1125*9deb0eb7SJason Gunthorpe 	if (chip->vendor.irq) {
1126*9deb0eb7SJason Gunthorpe again:
1127*9deb0eb7SJason Gunthorpe 		timeout = stop - jiffies;
1128*9deb0eb7SJason Gunthorpe 		if ((long)timeout <= 0)
1129*9deb0eb7SJason Gunthorpe 			return -ETIME;
1130*9deb0eb7SJason Gunthorpe 		rc = wait_event_interruptible_timeout(*queue,
1131*9deb0eb7SJason Gunthorpe 			wait_for_tpm_stat_cond(chip, mask, check_cancel,
1132*9deb0eb7SJason Gunthorpe 					       &canceled),
1133*9deb0eb7SJason Gunthorpe 			timeout);
1134*9deb0eb7SJason Gunthorpe 		if (rc > 0) {
1135*9deb0eb7SJason Gunthorpe 			if (canceled)
1136*9deb0eb7SJason Gunthorpe 				return -ECANCELED;
1137*9deb0eb7SJason Gunthorpe 			return 0;
1138*9deb0eb7SJason Gunthorpe 		}
1139*9deb0eb7SJason Gunthorpe 		if (rc == -ERESTARTSYS && freezing(current)) {
1140*9deb0eb7SJason Gunthorpe 			clear_thread_flag(TIF_SIGPENDING);
1141*9deb0eb7SJason Gunthorpe 			goto again;
1142*9deb0eb7SJason Gunthorpe 		}
1143*9deb0eb7SJason Gunthorpe 	} else {
1144*9deb0eb7SJason Gunthorpe 		do {
1145*9deb0eb7SJason Gunthorpe 			msleep(TPM_TIMEOUT);
1146*9deb0eb7SJason Gunthorpe 			status = chip->vendor.status(chip);
1147*9deb0eb7SJason Gunthorpe 			if ((status & mask) == mask)
1148*9deb0eb7SJason Gunthorpe 				return 0;
1149*9deb0eb7SJason Gunthorpe 		} while (time_before(jiffies, stop));
1150*9deb0eb7SJason Gunthorpe 	}
1151*9deb0eb7SJason Gunthorpe 	return -ETIME;
1152*9deb0eb7SJason Gunthorpe }
1153*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
1154*9deb0eb7SJason Gunthorpe /*
1155*9deb0eb7SJason Gunthorpe  * Device file system interface to the TPM
1156*9deb0eb7SJason Gunthorpe  *
1157*9deb0eb7SJason Gunthorpe  * It's assured that the chip will be opened just once,
1158*9deb0eb7SJason Gunthorpe  * by the check of is_open variable, which is protected
1159*9deb0eb7SJason Gunthorpe  * by driver_lock.
1160*9deb0eb7SJason Gunthorpe  */
1161*9deb0eb7SJason Gunthorpe int tpm_open(struct inode *inode, struct file *file)
1162*9deb0eb7SJason Gunthorpe {
1163*9deb0eb7SJason Gunthorpe 	struct miscdevice *misc = file->private_data;
1164*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = container_of(misc, struct tpm_chip,
1165*9deb0eb7SJason Gunthorpe 					     vendor.miscdev);
1166*9deb0eb7SJason Gunthorpe 
1167*9deb0eb7SJason Gunthorpe 	if (test_and_set_bit(0, &chip->is_open)) {
1168*9deb0eb7SJason Gunthorpe 		dev_dbg(chip->dev, "Another process owns this TPM\n");
1169*9deb0eb7SJason Gunthorpe 		return -EBUSY;
1170*9deb0eb7SJason Gunthorpe 	}
1171*9deb0eb7SJason Gunthorpe 
1172*9deb0eb7SJason Gunthorpe 	chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
1173*9deb0eb7SJason Gunthorpe 	if (chip->data_buffer == NULL) {
1174*9deb0eb7SJason Gunthorpe 		clear_bit(0, &chip->is_open);
1175*9deb0eb7SJason Gunthorpe 		return -ENOMEM;
1176*9deb0eb7SJason Gunthorpe 	}
1177*9deb0eb7SJason Gunthorpe 
1178*9deb0eb7SJason Gunthorpe 	atomic_set(&chip->data_pending, 0);
1179*9deb0eb7SJason Gunthorpe 
1180*9deb0eb7SJason Gunthorpe 	file->private_data = chip;
1181*9deb0eb7SJason Gunthorpe 	get_device(chip->dev);
1182*9deb0eb7SJason Gunthorpe 	return 0;
1183*9deb0eb7SJason Gunthorpe }
1184*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_open);
1185*9deb0eb7SJason Gunthorpe 
1186*9deb0eb7SJason Gunthorpe /*
1187*9deb0eb7SJason Gunthorpe  * Called on file close
1188*9deb0eb7SJason Gunthorpe  */
1189*9deb0eb7SJason Gunthorpe int tpm_release(struct inode *inode, struct file *file)
1190*9deb0eb7SJason Gunthorpe {
1191*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = file->private_data;
1192*9deb0eb7SJason Gunthorpe 
1193*9deb0eb7SJason Gunthorpe 	del_singleshot_timer_sync(&chip->user_read_timer);
1194*9deb0eb7SJason Gunthorpe 	flush_work(&chip->work);
1195*9deb0eb7SJason Gunthorpe 	file->private_data = NULL;
1196*9deb0eb7SJason Gunthorpe 	atomic_set(&chip->data_pending, 0);
1197*9deb0eb7SJason Gunthorpe 	kzfree(chip->data_buffer);
1198*9deb0eb7SJason Gunthorpe 	clear_bit(0, &chip->is_open);
1199*9deb0eb7SJason Gunthorpe 	put_device(chip->dev);
1200*9deb0eb7SJason Gunthorpe 	return 0;
1201*9deb0eb7SJason Gunthorpe }
1202*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_release);
1203*9deb0eb7SJason Gunthorpe 
1204*9deb0eb7SJason Gunthorpe ssize_t tpm_write(struct file *file, const char __user *buf,
1205*9deb0eb7SJason Gunthorpe 		  size_t size, loff_t *off)
1206*9deb0eb7SJason Gunthorpe {
1207*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = file->private_data;
1208*9deb0eb7SJason Gunthorpe 	size_t in_size = size;
1209*9deb0eb7SJason Gunthorpe 	ssize_t out_size;
1210*9deb0eb7SJason Gunthorpe 
1211*9deb0eb7SJason Gunthorpe 	/* cannot perform a write until the read has cleared
1212*9deb0eb7SJason Gunthorpe 	   either via tpm_read or a user_read_timer timeout.
1213*9deb0eb7SJason Gunthorpe 	   This also prevents splitted buffered writes from blocking here.
1214*9deb0eb7SJason Gunthorpe 	*/
1215*9deb0eb7SJason Gunthorpe 	if (atomic_read(&chip->data_pending) != 0)
1216*9deb0eb7SJason Gunthorpe 		return -EBUSY;
1217*9deb0eb7SJason Gunthorpe 
1218*9deb0eb7SJason Gunthorpe 	if (in_size > TPM_BUFSIZE)
1219*9deb0eb7SJason Gunthorpe 		return -E2BIG;
1220*9deb0eb7SJason Gunthorpe 
1221*9deb0eb7SJason Gunthorpe 	mutex_lock(&chip->buffer_mutex);
1222*9deb0eb7SJason Gunthorpe 
1223*9deb0eb7SJason Gunthorpe 	if (copy_from_user
1224*9deb0eb7SJason Gunthorpe 	    (chip->data_buffer, (void __user *) buf, in_size)) {
1225*9deb0eb7SJason Gunthorpe 		mutex_unlock(&chip->buffer_mutex);
1226*9deb0eb7SJason Gunthorpe 		return -EFAULT;
1227*9deb0eb7SJason Gunthorpe 	}
1228*9deb0eb7SJason Gunthorpe 
1229*9deb0eb7SJason Gunthorpe 	/* atomic tpm command send and result receive */
1230*9deb0eb7SJason Gunthorpe 	out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
1231*9deb0eb7SJason Gunthorpe 	if (out_size < 0) {
1232*9deb0eb7SJason Gunthorpe 		mutex_unlock(&chip->buffer_mutex);
1233*9deb0eb7SJason Gunthorpe 		return out_size;
1234*9deb0eb7SJason Gunthorpe 	}
1235*9deb0eb7SJason Gunthorpe 
1236*9deb0eb7SJason Gunthorpe 	atomic_set(&chip->data_pending, out_size);
1237*9deb0eb7SJason Gunthorpe 	mutex_unlock(&chip->buffer_mutex);
1238*9deb0eb7SJason Gunthorpe 
1239*9deb0eb7SJason Gunthorpe 	/* Set a timeout by which the reader must come claim the result */
1240*9deb0eb7SJason Gunthorpe 	mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
1241*9deb0eb7SJason Gunthorpe 
1242*9deb0eb7SJason Gunthorpe 	return in_size;
1243*9deb0eb7SJason Gunthorpe }
1244*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_write);
1245*9deb0eb7SJason Gunthorpe 
1246*9deb0eb7SJason Gunthorpe ssize_t tpm_read(struct file *file, char __user *buf,
1247*9deb0eb7SJason Gunthorpe 		 size_t size, loff_t *off)
1248*9deb0eb7SJason Gunthorpe {
1249*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = file->private_data;
1250*9deb0eb7SJason Gunthorpe 	ssize_t ret_size;
1251*9deb0eb7SJason Gunthorpe 	int rc;
1252*9deb0eb7SJason Gunthorpe 
1253*9deb0eb7SJason Gunthorpe 	del_singleshot_timer_sync(&chip->user_read_timer);
1254*9deb0eb7SJason Gunthorpe 	flush_work(&chip->work);
1255*9deb0eb7SJason Gunthorpe 	ret_size = atomic_read(&chip->data_pending);
1256*9deb0eb7SJason Gunthorpe 	if (ret_size > 0) {	/* relay data */
1257*9deb0eb7SJason Gunthorpe 		ssize_t orig_ret_size = ret_size;
1258*9deb0eb7SJason Gunthorpe 		if (size < ret_size)
1259*9deb0eb7SJason Gunthorpe 			ret_size = size;
1260*9deb0eb7SJason Gunthorpe 
1261*9deb0eb7SJason Gunthorpe 		mutex_lock(&chip->buffer_mutex);
1262*9deb0eb7SJason Gunthorpe 		rc = copy_to_user(buf, chip->data_buffer, ret_size);
1263*9deb0eb7SJason Gunthorpe 		memset(chip->data_buffer, 0, orig_ret_size);
1264*9deb0eb7SJason Gunthorpe 		if (rc)
1265*9deb0eb7SJason Gunthorpe 			ret_size = -EFAULT;
1266*9deb0eb7SJason Gunthorpe 
1267*9deb0eb7SJason Gunthorpe 		mutex_unlock(&chip->buffer_mutex);
1268*9deb0eb7SJason Gunthorpe 	}
1269*9deb0eb7SJason Gunthorpe 
1270*9deb0eb7SJason Gunthorpe 	atomic_set(&chip->data_pending, 0);
1271*9deb0eb7SJason Gunthorpe 
1272*9deb0eb7SJason Gunthorpe 	return ret_size;
1273*9deb0eb7SJason Gunthorpe }
1274*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_read);
1275*9deb0eb7SJason Gunthorpe 
1276*9deb0eb7SJason Gunthorpe void tpm_remove_hardware(struct device *dev)
1277*9deb0eb7SJason Gunthorpe {
1278*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1279*9deb0eb7SJason Gunthorpe 
1280*9deb0eb7SJason Gunthorpe 	if (chip == NULL) {
1281*9deb0eb7SJason Gunthorpe 		dev_err(dev, "No device data found\n");
1282*9deb0eb7SJason Gunthorpe 		return;
1283*9deb0eb7SJason Gunthorpe 	}
1284*9deb0eb7SJason Gunthorpe 
1285*9deb0eb7SJason Gunthorpe 	spin_lock(&driver_lock);
1286*9deb0eb7SJason Gunthorpe 	list_del_rcu(&chip->list);
1287*9deb0eb7SJason Gunthorpe 	spin_unlock(&driver_lock);
1288*9deb0eb7SJason Gunthorpe 	synchronize_rcu();
1289*9deb0eb7SJason Gunthorpe 
1290*9deb0eb7SJason Gunthorpe 	misc_deregister(&chip->vendor.miscdev);
1291*9deb0eb7SJason Gunthorpe 	sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
1292*9deb0eb7SJason Gunthorpe 	tpm_remove_ppi(&dev->kobj);
1293*9deb0eb7SJason Gunthorpe 	tpm_bios_log_teardown(chip->bios_dir);
1294*9deb0eb7SJason Gunthorpe 
1295*9deb0eb7SJason Gunthorpe 	/* write it this way to be explicit (chip->dev == dev) */
1296*9deb0eb7SJason Gunthorpe 	put_device(chip->dev);
1297*9deb0eb7SJason Gunthorpe }
1298*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_remove_hardware);
1299*9deb0eb7SJason Gunthorpe 
1300*9deb0eb7SJason Gunthorpe #define TPM_ORD_SAVESTATE cpu_to_be32(152)
1301*9deb0eb7SJason Gunthorpe #define SAVESTATE_RESULT_SIZE 10
1302*9deb0eb7SJason Gunthorpe 
1303*9deb0eb7SJason Gunthorpe static struct tpm_input_header savestate_header = {
1304*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
1305*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(10),
1306*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_SAVESTATE
1307*9deb0eb7SJason Gunthorpe };
1308*9deb0eb7SJason Gunthorpe 
1309*9deb0eb7SJason Gunthorpe /*
1310*9deb0eb7SJason Gunthorpe  * We are about to suspend. Save the TPM state
1311*9deb0eb7SJason Gunthorpe  * so that it can be restored.
1312*9deb0eb7SJason Gunthorpe  */
1313*9deb0eb7SJason Gunthorpe int tpm_pm_suspend(struct device *dev)
1314*9deb0eb7SJason Gunthorpe {
1315*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1316*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t cmd;
1317*9deb0eb7SJason Gunthorpe 	int rc, try;
1318*9deb0eb7SJason Gunthorpe 
1319*9deb0eb7SJason Gunthorpe 	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
1320*9deb0eb7SJason Gunthorpe 
1321*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
1322*9deb0eb7SJason Gunthorpe 		return -ENODEV;
1323*9deb0eb7SJason Gunthorpe 
1324*9deb0eb7SJason Gunthorpe 	/* for buggy tpm, flush pcrs with extend to selected dummy */
1325*9deb0eb7SJason Gunthorpe 	if (tpm_suspend_pcr) {
1326*9deb0eb7SJason Gunthorpe 		cmd.header.in = pcrextend_header;
1327*9deb0eb7SJason Gunthorpe 		cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
1328*9deb0eb7SJason Gunthorpe 		memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
1329*9deb0eb7SJason Gunthorpe 		       TPM_DIGEST_SIZE);
1330*9deb0eb7SJason Gunthorpe 		rc = transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
1331*9deb0eb7SJason Gunthorpe 				  "extending dummy pcr before suspend");
1332*9deb0eb7SJason Gunthorpe 	}
1333*9deb0eb7SJason Gunthorpe 
1334*9deb0eb7SJason Gunthorpe 	/* now do the actual savestate */
1335*9deb0eb7SJason Gunthorpe 	for (try = 0; try < TPM_RETRY; try++) {
1336*9deb0eb7SJason Gunthorpe 		cmd.header.in = savestate_header;
1337*9deb0eb7SJason Gunthorpe 		rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
1338*9deb0eb7SJason Gunthorpe 
1339*9deb0eb7SJason Gunthorpe 		/*
1340*9deb0eb7SJason Gunthorpe 		 * If the TPM indicates that it is too busy to respond to
1341*9deb0eb7SJason Gunthorpe 		 * this command then retry before giving up.  It can take
1342*9deb0eb7SJason Gunthorpe 		 * several seconds for this TPM to be ready.
1343*9deb0eb7SJason Gunthorpe 		 *
1344*9deb0eb7SJason Gunthorpe 		 * This can happen if the TPM has already been sent the
1345*9deb0eb7SJason Gunthorpe 		 * SaveState command before the driver has loaded.  TCG 1.2
1346*9deb0eb7SJason Gunthorpe 		 * specification states that any communication after SaveState
1347*9deb0eb7SJason Gunthorpe 		 * may cause the TPM to invalidate previously saved state.
1348*9deb0eb7SJason Gunthorpe 		 */
1349*9deb0eb7SJason Gunthorpe 		if (rc != TPM_WARN_RETRY)
1350*9deb0eb7SJason Gunthorpe 			break;
1351*9deb0eb7SJason Gunthorpe 		msleep(TPM_TIMEOUT_RETRY);
1352*9deb0eb7SJason Gunthorpe 	}
1353*9deb0eb7SJason Gunthorpe 
1354*9deb0eb7SJason Gunthorpe 	if (rc)
1355*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
1356*9deb0eb7SJason Gunthorpe 			"Error (%d) sending savestate before suspend\n", rc);
1357*9deb0eb7SJason Gunthorpe 	else if (try > 0)
1358*9deb0eb7SJason Gunthorpe 		dev_warn(chip->dev, "TPM savestate took %dms\n",
1359*9deb0eb7SJason Gunthorpe 			 try * TPM_TIMEOUT_RETRY);
1360*9deb0eb7SJason Gunthorpe 
1361*9deb0eb7SJason Gunthorpe 	return rc;
1362*9deb0eb7SJason Gunthorpe }
1363*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pm_suspend);
1364*9deb0eb7SJason Gunthorpe 
1365*9deb0eb7SJason Gunthorpe /*
1366*9deb0eb7SJason Gunthorpe  * Resume from a power safe. The BIOS already restored
1367*9deb0eb7SJason Gunthorpe  * the TPM state.
1368*9deb0eb7SJason Gunthorpe  */
1369*9deb0eb7SJason Gunthorpe int tpm_pm_resume(struct device *dev)
1370*9deb0eb7SJason Gunthorpe {
1371*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1372*9deb0eb7SJason Gunthorpe 
1373*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
1374*9deb0eb7SJason Gunthorpe 		return -ENODEV;
1375*9deb0eb7SJason Gunthorpe 
1376*9deb0eb7SJason Gunthorpe 	return 0;
1377*9deb0eb7SJason Gunthorpe }
1378*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_pm_resume);
1379*9deb0eb7SJason Gunthorpe 
1380*9deb0eb7SJason Gunthorpe #define TPM_GETRANDOM_RESULT_SIZE	18
1381*9deb0eb7SJason Gunthorpe static struct tpm_input_header tpm_getrandom_header = {
1382*9deb0eb7SJason Gunthorpe 	.tag = TPM_TAG_RQU_COMMAND,
1383*9deb0eb7SJason Gunthorpe 	.length = cpu_to_be32(14),
1384*9deb0eb7SJason Gunthorpe 	.ordinal = TPM_ORD_GET_RANDOM
1385*9deb0eb7SJason Gunthorpe };
1386*9deb0eb7SJason Gunthorpe 
1387*9deb0eb7SJason Gunthorpe /**
1388*9deb0eb7SJason Gunthorpe  * tpm_get_random() - Get random bytes from the tpm's RNG
1389*9deb0eb7SJason Gunthorpe  * @chip_num: A specific chip number for the request or TPM_ANY_NUM
1390*9deb0eb7SJason Gunthorpe  * @out: destination buffer for the random bytes
1391*9deb0eb7SJason Gunthorpe  * @max: the max number of bytes to write to @out
1392*9deb0eb7SJason Gunthorpe  *
1393*9deb0eb7SJason Gunthorpe  * Returns < 0 on error and the number of bytes read on success
1394*9deb0eb7SJason Gunthorpe  */
1395*9deb0eb7SJason Gunthorpe int tpm_get_random(u32 chip_num, u8 *out, size_t max)
1396*9deb0eb7SJason Gunthorpe {
1397*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip;
1398*9deb0eb7SJason Gunthorpe 	struct tpm_cmd_t tpm_cmd;
1399*9deb0eb7SJason Gunthorpe 	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
1400*9deb0eb7SJason Gunthorpe 	int err, total = 0, retries = 5;
1401*9deb0eb7SJason Gunthorpe 	u8 *dest = out;
1402*9deb0eb7SJason Gunthorpe 
1403*9deb0eb7SJason Gunthorpe 	chip = tpm_chip_find_get(chip_num);
1404*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
1405*9deb0eb7SJason Gunthorpe 		return -ENODEV;
1406*9deb0eb7SJason Gunthorpe 
1407*9deb0eb7SJason Gunthorpe 	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
1408*9deb0eb7SJason Gunthorpe 		return -EINVAL;
1409*9deb0eb7SJason Gunthorpe 
1410*9deb0eb7SJason Gunthorpe 	do {
1411*9deb0eb7SJason Gunthorpe 		tpm_cmd.header.in = tpm_getrandom_header;
1412*9deb0eb7SJason Gunthorpe 		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
1413*9deb0eb7SJason Gunthorpe 
1414*9deb0eb7SJason Gunthorpe 		err = transmit_cmd(chip, &tpm_cmd,
1415*9deb0eb7SJason Gunthorpe 				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
1416*9deb0eb7SJason Gunthorpe 				   "attempting get random");
1417*9deb0eb7SJason Gunthorpe 		if (err)
1418*9deb0eb7SJason Gunthorpe 			break;
1419*9deb0eb7SJason Gunthorpe 
1420*9deb0eb7SJason Gunthorpe 		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
1421*9deb0eb7SJason Gunthorpe 		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
1422*9deb0eb7SJason Gunthorpe 
1423*9deb0eb7SJason Gunthorpe 		dest += recd;
1424*9deb0eb7SJason Gunthorpe 		total += recd;
1425*9deb0eb7SJason Gunthorpe 		num_bytes -= recd;
1426*9deb0eb7SJason Gunthorpe 	} while (retries-- && total < max);
1427*9deb0eb7SJason Gunthorpe 
1428*9deb0eb7SJason Gunthorpe 	return total ? total : -EIO;
1429*9deb0eb7SJason Gunthorpe }
1430*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_get_random);
1431*9deb0eb7SJason Gunthorpe 
1432*9deb0eb7SJason Gunthorpe /* In case vendor provided release function, call it too.*/
1433*9deb0eb7SJason Gunthorpe 
1434*9deb0eb7SJason Gunthorpe void tpm_dev_vendor_release(struct tpm_chip *chip)
1435*9deb0eb7SJason Gunthorpe {
1436*9deb0eb7SJason Gunthorpe 	if (!chip)
1437*9deb0eb7SJason Gunthorpe 		return;
1438*9deb0eb7SJason Gunthorpe 
1439*9deb0eb7SJason Gunthorpe 	if (chip->vendor.release)
1440*9deb0eb7SJason Gunthorpe 		chip->vendor.release(chip->dev);
1441*9deb0eb7SJason Gunthorpe 
1442*9deb0eb7SJason Gunthorpe 	clear_bit(chip->dev_num, dev_mask);
1443*9deb0eb7SJason Gunthorpe }
1444*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
1445*9deb0eb7SJason Gunthorpe 
1446*9deb0eb7SJason Gunthorpe 
1447*9deb0eb7SJason Gunthorpe /*
1448*9deb0eb7SJason Gunthorpe  * Once all references to platform device are down to 0,
1449*9deb0eb7SJason Gunthorpe  * release all allocated structures.
1450*9deb0eb7SJason Gunthorpe  */
1451*9deb0eb7SJason Gunthorpe void tpm_dev_release(struct device *dev)
1452*9deb0eb7SJason Gunthorpe {
1453*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip = dev_get_drvdata(dev);
1454*9deb0eb7SJason Gunthorpe 
1455*9deb0eb7SJason Gunthorpe 	if (!chip)
1456*9deb0eb7SJason Gunthorpe 		return;
1457*9deb0eb7SJason Gunthorpe 
1458*9deb0eb7SJason Gunthorpe 	tpm_dev_vendor_release(chip);
1459*9deb0eb7SJason Gunthorpe 
1460*9deb0eb7SJason Gunthorpe 	chip->release(dev);
1461*9deb0eb7SJason Gunthorpe 	kfree(chip);
1462*9deb0eb7SJason Gunthorpe }
1463*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_dev_release);
1464*9deb0eb7SJason Gunthorpe 
1465*9deb0eb7SJason Gunthorpe /*
1466*9deb0eb7SJason Gunthorpe  * Called from tpm_<specific>.c probe function only for devices
1467*9deb0eb7SJason Gunthorpe  * the driver has determined it should claim.  Prior to calling
1468*9deb0eb7SJason Gunthorpe  * this function the specific probe function has called pci_enable_device
1469*9deb0eb7SJason Gunthorpe  * upon errant exit from this function specific probe function should call
1470*9deb0eb7SJason Gunthorpe  * pci_disable_device
1471*9deb0eb7SJason Gunthorpe  */
1472*9deb0eb7SJason Gunthorpe struct tpm_chip *tpm_register_hardware(struct device *dev,
1473*9deb0eb7SJason Gunthorpe 					const struct tpm_vendor_specific *entry)
1474*9deb0eb7SJason Gunthorpe {
1475*9deb0eb7SJason Gunthorpe 	struct tpm_chip *chip;
1476*9deb0eb7SJason Gunthorpe 
1477*9deb0eb7SJason Gunthorpe 	/* Driver specific per-device data */
1478*9deb0eb7SJason Gunthorpe 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1479*9deb0eb7SJason Gunthorpe 
1480*9deb0eb7SJason Gunthorpe 	if (chip == NULL)
1481*9deb0eb7SJason Gunthorpe 		return NULL;
1482*9deb0eb7SJason Gunthorpe 
1483*9deb0eb7SJason Gunthorpe 	mutex_init(&chip->buffer_mutex);
1484*9deb0eb7SJason Gunthorpe 	mutex_init(&chip->tpm_mutex);
1485*9deb0eb7SJason Gunthorpe 	INIT_LIST_HEAD(&chip->list);
1486*9deb0eb7SJason Gunthorpe 
1487*9deb0eb7SJason Gunthorpe 	INIT_WORK(&chip->work, timeout_work);
1488*9deb0eb7SJason Gunthorpe 
1489*9deb0eb7SJason Gunthorpe 	setup_timer(&chip->user_read_timer, user_reader_timeout,
1490*9deb0eb7SJason Gunthorpe 			(unsigned long)chip);
1491*9deb0eb7SJason Gunthorpe 
1492*9deb0eb7SJason Gunthorpe 	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
1493*9deb0eb7SJason Gunthorpe 
1494*9deb0eb7SJason Gunthorpe 	chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
1495*9deb0eb7SJason Gunthorpe 
1496*9deb0eb7SJason Gunthorpe 	if (chip->dev_num >= TPM_NUM_DEVICES) {
1497*9deb0eb7SJason Gunthorpe 		dev_err(dev, "No available tpm device numbers\n");
1498*9deb0eb7SJason Gunthorpe 		goto out_free;
1499*9deb0eb7SJason Gunthorpe 	} else if (chip->dev_num == 0)
1500*9deb0eb7SJason Gunthorpe 		chip->vendor.miscdev.minor = TPM_MINOR;
1501*9deb0eb7SJason Gunthorpe 	else
1502*9deb0eb7SJason Gunthorpe 		chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
1503*9deb0eb7SJason Gunthorpe 
1504*9deb0eb7SJason Gunthorpe 	set_bit(chip->dev_num, dev_mask);
1505*9deb0eb7SJason Gunthorpe 
1506*9deb0eb7SJason Gunthorpe 	scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm",
1507*9deb0eb7SJason Gunthorpe 		  chip->dev_num);
1508*9deb0eb7SJason Gunthorpe 	chip->vendor.miscdev.name = chip->devname;
1509*9deb0eb7SJason Gunthorpe 
1510*9deb0eb7SJason Gunthorpe 	chip->vendor.miscdev.parent = dev;
1511*9deb0eb7SJason Gunthorpe 	chip->dev = get_device(dev);
1512*9deb0eb7SJason Gunthorpe 	chip->release = dev->release;
1513*9deb0eb7SJason Gunthorpe 	dev->release = tpm_dev_release;
1514*9deb0eb7SJason Gunthorpe 	dev_set_drvdata(dev, chip);
1515*9deb0eb7SJason Gunthorpe 
1516*9deb0eb7SJason Gunthorpe 	if (misc_register(&chip->vendor.miscdev)) {
1517*9deb0eb7SJason Gunthorpe 		dev_err(chip->dev,
1518*9deb0eb7SJason Gunthorpe 			"unable to misc_register %s, minor %d\n",
1519*9deb0eb7SJason Gunthorpe 			chip->vendor.miscdev.name,
1520*9deb0eb7SJason Gunthorpe 			chip->vendor.miscdev.minor);
1521*9deb0eb7SJason Gunthorpe 		goto put_device;
1522*9deb0eb7SJason Gunthorpe 	}
1523*9deb0eb7SJason Gunthorpe 
1524*9deb0eb7SJason Gunthorpe 	if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
1525*9deb0eb7SJason Gunthorpe 		misc_deregister(&chip->vendor.miscdev);
1526*9deb0eb7SJason Gunthorpe 		goto put_device;
1527*9deb0eb7SJason Gunthorpe 	}
1528*9deb0eb7SJason Gunthorpe 
1529*9deb0eb7SJason Gunthorpe 	if (tpm_add_ppi(&dev->kobj)) {
1530*9deb0eb7SJason Gunthorpe 		misc_deregister(&chip->vendor.miscdev);
1531*9deb0eb7SJason Gunthorpe 		goto put_device;
1532*9deb0eb7SJason Gunthorpe 	}
1533*9deb0eb7SJason Gunthorpe 
1534*9deb0eb7SJason Gunthorpe 	chip->bios_dir = tpm_bios_log_setup(chip->devname);
1535*9deb0eb7SJason Gunthorpe 
1536*9deb0eb7SJason Gunthorpe 	/* Make chip available */
1537*9deb0eb7SJason Gunthorpe 	spin_lock(&driver_lock);
1538*9deb0eb7SJason Gunthorpe 	list_add_rcu(&chip->list, &tpm_chip_list);
1539*9deb0eb7SJason Gunthorpe 	spin_unlock(&driver_lock);
1540*9deb0eb7SJason Gunthorpe 
1541*9deb0eb7SJason Gunthorpe 	return chip;
1542*9deb0eb7SJason Gunthorpe 
1543*9deb0eb7SJason Gunthorpe put_device:
1544*9deb0eb7SJason Gunthorpe 	put_device(chip->dev);
1545*9deb0eb7SJason Gunthorpe out_free:
1546*9deb0eb7SJason Gunthorpe 	kfree(chip);
1547*9deb0eb7SJason Gunthorpe 	return NULL;
1548*9deb0eb7SJason Gunthorpe }
1549*9deb0eb7SJason Gunthorpe EXPORT_SYMBOL_GPL(tpm_register_hardware);
1550*9deb0eb7SJason Gunthorpe 
1551*9deb0eb7SJason Gunthorpe MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
1552*9deb0eb7SJason Gunthorpe MODULE_DESCRIPTION("TPM Driver");
1553*9deb0eb7SJason Gunthorpe MODULE_VERSION("2.0");
1554*9deb0eb7SJason Gunthorpe MODULE_LICENSE("GPL");
1555