blob: c0429ddc9cf307c8e4b49b621f172dce2a0e3379 [file] [log] [blame]
Stefan Reinauer3008bbad2011-10-11 14:46:25 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*
21 * The code in this file has been heavily based on the article "Writing a TPM
22 * Device Driver" published on http://ptgmedia.pearsoncmg.com and the
23 * submission by Stefan Berger on Qemu-devel mailing list.
24 *
25 * One principal difference is that in the simplest config the other than 0
26 * TPM localities do not get mapped by some devices (for instance, by
27 * Infineon slb9635), so this driver provides access to locality 0 only.
28 */
29
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070030#include <stdlib.h>
31#include <string.h>
32#include <delay.h>
33#include <arch/io.h>
34#include <arch/byteorder.h>
35#include <console/console.h>
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080036#include <tpm.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070037#include <arch/early_variables.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070038
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070039#define PREFIX "lpc_tpm: "
40
41/* coreboot wrapper for TPM driver (start) */
42#define TPM_DEBUG(fmt, args...) \
Stefan Reinauerdfb098d2011-11-17 12:50:54 -080043 if (CONFIG_DEBUG_TPM) { \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070044 printk(BIOS_DEBUG, PREFIX); \
45 printk(BIOS_DEBUG, fmt , ##args); \
46 }
Aaron Durbinc4220022013-07-24 16:02:14 -050047#define TPM_DEBUG_IO_READ(reg_, val_) \
48 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_))
49#define TPM_DEBUG_IO_WRITE(reg_, val_) \
50 TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070051#define printf(x...) printk(BIOS_ERR, x)
52
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070053#define readb(_a) (*(volatile unsigned char *) (_a))
54#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v))
55#define readl(_a) (*(volatile unsigned long *) (_a))
56#define writel(_v, _a) (*(volatile unsigned long *) (_a) = (_v))
57/* coreboot wrapper for TPM driver (end) */
58
59#ifndef CONFIG_TPM_TIS_BASE_ADDRESS
60/* Base TPM address standard for x86 systems */
61#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
62#endif
63
64/* the macro accepts the locality value, but only locality 0 is operational */
65#define TIS_REG(LOCALITY, REG) \
66 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
67
68/* hardware registers' offsets */
69#define TIS_REG_ACCESS 0x0
70#define TIS_REG_INT_ENABLE 0x8
71#define TIS_REG_INT_VECTOR 0xc
72#define TIS_REG_INT_STATUS 0x10
73#define TIS_REG_INTF_CAPABILITY 0x14
74#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050075#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070076#define TIS_REG_DATA_FIFO 0x24
77#define TIS_REG_DID_VID 0xf00
78#define TIS_REG_RID 0xf04
79
80/* Some registers' bit field definitions */
81#define TIS_STS_VALID (1 << 7) /* 0x80 */
82#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
83#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
84#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
85#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
86#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
87
88#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
89#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
90#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
91#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
92#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
93#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
94#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
95
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070096/*
97 * Error value returned if a tpm register does not enter the expected state
98 * after continuous polling. No actual TPM register reading ever returns ~0,
99 * so this value is a safe error indication to be mixed with possible status
100 * register values.
101 */
102#define TPM_TIMEOUT_ERR (~0)
103
104/* Error value returned on various TPM driver errors */
105#define TPM_DRIVER_ERR (~0)
106
107 /* 1 second is plenty for anything TPM does.*/
108#define MAX_DELAY_US (1000 * 1000)
109
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700110/*
111 * Structures defined below allow creating descriptions of TPM vendor/device
112 * ID information for run time discovery. The only device the system knows
113 * about at this time is Infineon slb9635
114 */
115struct device_name {
116 u16 dev_id;
117 const char * const dev_name;
118};
119
120struct vendor_name {
121 u16 vendor_id;
122 const char * vendor_name;
Stefan Reinauerc668af72011-10-27 21:28:25 +0000123 const struct device_name* dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700124};
125
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700126static const struct device_name atmel_devices[] = {
127 {0x3204, "AT97SC3204"},
128 {0xffff}
129};
130
Stefan Reinauerc668af72011-10-27 21:28:25 +0000131static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700132 {0x000b, "SLB9635 TT 1.2"},
133 {0xffff}
134};
135
136static const struct device_name nuvoton_devices[] = {
137 {0x00fe, "NPCT420AA V2"},
138 {0xffff}
139};
140
141static const struct device_name stmicro_devices[] = {
142 {0x0000, "ST33ZP24" },
143 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700144};
145
146static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700147 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700148 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700149 {0x1050, "Nuvoton", nuvoton_devices},
150 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700151};
152
153/*
154 * Cached vendor/device ID pair to indicate that the device has been already
155 * discovered
156 */
Stefan Reinauerc668af72011-10-27 21:28:25 +0000157static u32 vendor_dev_id CAR_GLOBAL;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700158
Aaron Durbinc4220022013-07-24 16:02:14 -0500159static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700160{
Aaron Durbinc4220022013-07-24 16:02:14 -0500161 u8 value = readb(TIS_REG(locality, TIS_REG_STS));
162 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700163 return value;
164}
165
Aaron Durbinc4220022013-07-24 16:02:14 -0500166static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700167{
Aaron Durbinc4220022013-07-24 16:02:14 -0500168 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
169 writeb(sts, TIS_REG(locality, TIS_REG_STS));
170}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700171
Aaron Durbinc4220022013-07-24 16:02:14 -0500172static inline u8 tpm_read_data(int locality)
173{
174 u8 value = readb(TIS_REG(locality, TIS_REG_DATA_FIFO));
175 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
176 return value;
177}
178
179static inline void tpm_write_data(u8 data, int locality)
180{
181 TPM_DEBUG_IO_WRITE(TIS_REG_STS, data);
182 writeb(data, TIS_REG(locality, TIS_REG_DATA_FIFO));
183}
184
185static inline u16 tpm_read_burst_count(int locality)
186{
187 u16 count;
188 count = readb(TIS_REG(locality, TIS_REG_BURST_COUNT));
189 count |= readb(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
190 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
191 return count;
192}
193
194static inline u8 tpm_read_access(int locality)
195{
196 u8 value = readb(TIS_REG(locality, TIS_REG_ACCESS));
197 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
198 return value;
199}
200
201static inline void tpm_write_access(u8 data, int locality)
202{
203 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
204 writeb(data, TIS_REG(locality, TIS_REG_ACCESS));
205}
206
207static inline u32 tpm_read_did_vid(int locality)
208{
209 u32 value = readl(TIS_REG(locality, TIS_REG_DID_VID));
210 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
211 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700212}
213
214/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500215 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700216 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500217 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700218 * expected state. Normally the transition happens within microseconds.
219 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700220 * @locality - locality
221 * @mask - bitmask for the bitfield(s) to watch
222 * @expected - value the field(s) are supposed to be set to
223 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500224 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700225 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500226static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700227{
228 u32 time_us = MAX_DELAY_US;
229 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500230 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700231 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500232 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700233 udelay(1); /* 1 us */
234 time_us--;
235 }
236 return TPM_TIMEOUT_ERR;
237}
238
Aaron Durbinc4220022013-07-24 16:02:14 -0500239static inline int tis_wait_ready(int locality)
240{
241 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
242 TIS_STS_COMMAND_READY);
243}
244
245static inline int tis_wait_valid(int locality)
246{
247 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
248}
249
250static inline int tis_wait_valid_data(int locality)
251{
252 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
253 return tis_wait_sts(locality, has_data, has_data);
254}
255
256static inline int tis_has_valid_data(int locality)
257{
258 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
259 return (tpm_read_status(locality) & has_data) == has_data;
260}
261
262static inline int tis_expect_data(int locality)
263{
264 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
265}
266
267/*
268 * tis_wait_access()
269 *
270 * Wait for at least a second for a access to change its state to match the
271 * expected state. Normally the transition happens within microseconds.
272 *
273 * @locality - locality
274 * @mask - bitmask for the bitfield(s) to watch
275 * @expected - value the field(s) are supposed to be set to
276 *
277 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
278 */
279static int tis_wait_access(int locality, u8 mask, u8 expected)
280{
281 u32 time_us = MAX_DELAY_US;
282 while (time_us > 0) {
283 u8 value = tpm_read_access(locality);
284 if ((value & mask) == expected)
285 return 0;
286 udelay(1); /* 1 us */
287 time_us--;
288 }
289 return TPM_TIMEOUT_ERR;
290}
291
292static inline int tis_wait_dropped_access(int locality)
293{
294 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
295}
296
297static inline int tis_wait_received_access(int locality)
298{
299 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
300 TIS_ACCESS_ACTIVE_LOCALITY);
301}
302
303static inline int tis_has_access(int locality)
304{
305 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
306}
307
308static inline void tis_request_access(int locality)
309{
310 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
311}
312
313static inline void tis_drop_access(int locality)
314{
315 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
316}
317
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700318/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700319 * PC Client Specific TPM Interface Specification section 11.2.12:
320 *
321 * Software must be prepared to send two writes of a "1" to command ready
322 * field: the first to indicate successful read of all the data, thus
323 * clearing the data from the ReadFIFO and freeing the TPM's resources,
324 * and the second to indicate to the TPM it is about to send a new command.
325 *
326 * In practice not all TPMs behave the same so it is necessary to be
327 * flexible when trying to set command ready.
328 *
329 * Returns 0 on success if the TPM is ready for transactions.
330 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
331 */
332static int tis_command_ready(u8 locality)
333{
334 u32 status;
335
336 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500337 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700338
339 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500340 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700341
342 /* Check if command ready is set yet */
343 if (status & TIS_STS_COMMAND_READY)
344 return 0;
345
346 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500347 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700348
Aaron Durbinc4220022013-07-24 16:02:14 -0500349 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700350}
351
352/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700353 * Probe the TPM device and try determining its manufacturer/device name.
354 *
355 * Returns 0 on success (the device is found or was found during an earlier
356 * invocation) or TPM_DRIVER_ERR if the device is not found.
357 */
358static u32 tis_probe(void)
359{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700360 const char *device_name = "unknown";
361 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700362 const struct device_name *dev;
363 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700364 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700365 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700366
Aaron Durbincb997d32013-05-10 00:40:56 -0500367 if (car_get_var(vendor_dev_id))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700368 return 0; /* Already probed. */
369
Aaron Durbinc4220022013-07-24 16:02:14 -0500370 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700371 if (!didvid || (didvid == 0xffffffff)) {
372 printf("%s: No TPM device found\n", __FUNCTION__);
373 return TPM_DRIVER_ERR;
374 }
375
Aaron Durbincb997d32013-05-10 00:40:56 -0500376 car_set_var(vendor_dev_id, didvid);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700377
378 vid = didvid & 0xffff;
379 did = (didvid >> 16) & 0xffff;
380 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
381 int j = 0;
382 u16 known_did;
383 if (vid == vendor_names[i].vendor_id) {
384 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700385 } else {
386 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700387 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700388 dev = &vendor_names[i].dev_names[j];
389 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700390 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700391 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700392 break;
393 }
394 j++;
395 }
396 break;
397 }
398 /* this will have to be converted into debug printout */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700399 printf("Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700400 return 0;
401}
402
403/*
404 * tis_senddata()
405 *
406 * send the passed in data to the TPM device.
407 *
408 * @data - address of the data to send, byte by byte
409 * @len - length of the data to send
410 *
411 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
412 * not accept the entire command).
413 */
414static u32 tis_senddata(const u8 * const data, u32 len)
415{
416 u32 offset = 0;
417 u16 burst = 0;
418 u32 max_cycles = 0;
419 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700420
Aaron Durbinc4220022013-07-24 16:02:14 -0500421 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700422 printf("%s:%d - failed to get 'command_ready' status\n",
423 __FILE__, __LINE__);
424 return TPM_DRIVER_ERR;
425 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500426 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700427
428 while (1) {
429 unsigned count;
430
431 /* Wait till the device is ready to accept more data. */
432 while (!burst) {
433 if (max_cycles++ == MAX_DELAY_US) {
434 printf("%s:%d failed to feed %d bytes of %d\n",
435 __FILE__, __LINE__, len - offset, len);
436 return TPM_DRIVER_ERR;
437 }
438 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500439 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700440 }
441
442 max_cycles = 0;
443
444 /*
445 * Calculate number of bytes the TPM is ready to accept in one
446 * shot.
447 *
448 * We want to send the last byte outside of the loop (hence
449 * the -1 below) to make sure that the 'expected' status bit
450 * changes to zero exactly after the last byte is fed into the
451 * FIFO.
452 */
453 count = min(burst, len - offset - 1);
454 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500455 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700456
Aaron Durbinc4220022013-07-24 16:02:14 -0500457 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700458 printf("%s:%d TPM command feed overflow\n",
459 __FILE__, __LINE__);
460 return TPM_DRIVER_ERR;
461 }
462
Aaron Durbinc4220022013-07-24 16:02:14 -0500463 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700464 if ((offset == (len - 1)) && burst)
465 /*
466 * We need to be able to send the last byte to the
467 * device, so burst size must be nonzero before we
468 * break out.
469 */
470 break;
471 }
472
473 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500474 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700475
476 /*
477 * Verify that TPM does not expect any more data as part of this
478 * command.
479 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500480 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700481 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500482 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700483 return TPM_DRIVER_ERR;
484 }
485
486 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500487 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700488
489 return 0;
490}
491
492/*
493 * tis_readresponse()
494 *
495 * read the TPM device response after a command was issued.
496 *
497 * @buffer - address where to read the response, byte by byte.
498 * @len - pointer to the size of buffer
499 *
500 * On success stores the number of received bytes to len and returns 0. On
501 * errors (misformatted TPM data or synchronization problems) returns
502 * TPM_DRIVER_ERR.
503 */
504static u32 tis_readresponse(u8 *buffer, size_t *len)
505{
506 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700507 u32 offset = 0;
508 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700509 u32 expected_count = *len;
510 int max_cycles = 0;
511
512 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500513 if (tis_wait_valid_data(locality)) {
514 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700515 return TPM_DRIVER_ERR;
516 }
517
518 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500519 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700520 if (max_cycles++ == MAX_DELAY_US) {
521 printf("%s:%d TPM stuck on read\n",
522 __FILE__, __LINE__);
523 return TPM_DRIVER_ERR;
524 }
525 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700526 }
527
528 max_cycles = 0;
529
530 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500531 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700532 if (offset == 6) {
533 /*
534 * We got the first six bytes of the reply,
535 * let's figure out how many bytes to expect
536 * total - it is stored as a 4 byte number in
537 * network order, starting with offset 2 into
538 * the body of the reply.
539 */
540 u32 real_length;
541 memcpy(&real_length,
542 buffer + 2,
543 sizeof(real_length));
544 expected_count = be32_to_cpu(real_length);
545
546 if ((expected_count < offset) ||
547 (expected_count > *len)) {
548 printf("%s:%d bad response size %d\n",
549 __FILE__, __LINE__,
550 expected_count);
551 return TPM_DRIVER_ERR;
552 }
553 }
554 }
555
556 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500557 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700558 printf("%s:%d failed to read response\n",
559 __FILE__, __LINE__);
560 return TPM_DRIVER_ERR;
561 }
562
563 if (offset == expected_count)
564 break; /* We got all we need */
565
Aaron Durbinc4220022013-07-24 16:02:14 -0500566 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700567
Aaron Durbinc4220022013-07-24 16:02:14 -0500568 /* * Make sure we indeed read all there was. */
569 if (tis_has_valid_data(locality)) {
570 printf("%s:%d wrong receive status: %x %d bytes left\n",
571 __FILE__, __LINE__, tpm_read_status(locality),
572 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700573 return TPM_DRIVER_ERR;
574 }
575
576 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700577 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
578 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700579
580 *len = offset;
581 return 0;
582}
583
584/*
585 * tis_init()
586 *
587 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
588 * failure (in case device probing did not succeed).
589 */
590int tis_init(void)
591{
592 if (tis_probe())
593 return TPM_DRIVER_ERR;
594 return 0;
595}
596
597/*
598 * tis_open()
599 *
600 * Requests access to locality 0 for the caller. After all commands have been
601 * completed the caller is supposed to call tis_close().
602 *
603 * Returns 0 on success, TPM_DRIVER_ERR on failure.
604 */
605int tis_open(void)
606{
607 u8 locality = 0; /* we use locality zero for everything */
608
609 if (tis_close())
610 return TPM_DRIVER_ERR;
611
612 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500613 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700614
615 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500616 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700617 printf("%s:%d - failed to lock locality %d\n",
618 __FILE__, __LINE__, locality);
619 return TPM_DRIVER_ERR;
620 }
621
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700622 /* Certain TPMs seem to need some delay here or they hang... */
623 udelay(10);
624
625 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
626 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700627
628 return 0;
629}
630
631/*
632 * tis_close()
633 *
Martin Roth56889792013-07-09 21:39:46 -0600634 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700635 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
636 * removal did not succeed).
637 */
638int tis_close(void)
639{
640 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500641 if (tis_has_access(locality)) {
642 tis_drop_access(locality);
643 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700644 printf("%s:%d - failed to release locality %d\n",
645 __FILE__, __LINE__, locality);
646 return TPM_DRIVER_ERR;
647 }
648 }
649 return 0;
650}
651
652/*
653 * tis_sendrecv()
654 *
655 * Send the requested data to the TPM and then try to get its response
656 *
657 * @sendbuf - buffer of the data to send
658 * @send_size size of the data to send
659 * @recvbuf - memory to save the response to
660 * @recv_len - pointer to the size of the response buffer
661 *
662 * Returns 0 on success (and places the number of response bytes at recv_len)
663 * or TPM_DRIVER_ERR on failure.
664 */
665int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
666 uint8_t *recvbuf, size_t *recv_len)
667{
668 if (tis_senddata(sendbuf, send_size)) {
669 printf("%s:%d failed sending data to TPM\n",
670 __FILE__, __LINE__);
671 return TPM_DRIVER_ERR;
672 }
673
674 return tis_readresponse(recvbuf, recv_len);
675}