blob: f581ab49d32a8b63f5de729429c5d111055327b7 [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>
36#include <pc80/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
53#define min(a,b) MIN(a,b)
54#define max(a,b) MAX(a,b)
55#define readb(_a) (*(volatile unsigned char *) (_a))
56#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v))
57#define readl(_a) (*(volatile unsigned long *) (_a))
58#define writel(_v, _a) (*(volatile unsigned long *) (_a) = (_v))
59/* coreboot wrapper for TPM driver (end) */
60
61#ifndef CONFIG_TPM_TIS_BASE_ADDRESS
62/* Base TPM address standard for x86 systems */
63#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
64#endif
65
66/* the macro accepts the locality value, but only locality 0 is operational */
67#define TIS_REG(LOCALITY, REG) \
68 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
69
70/* hardware registers' offsets */
71#define TIS_REG_ACCESS 0x0
72#define TIS_REG_INT_ENABLE 0x8
73#define TIS_REG_INT_VECTOR 0xc
74#define TIS_REG_INT_STATUS 0x10
75#define TIS_REG_INTF_CAPABILITY 0x14
76#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050077#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070078#define TIS_REG_DATA_FIFO 0x24
79#define TIS_REG_DID_VID 0xf00
80#define TIS_REG_RID 0xf04
81
82/* Some registers' bit field definitions */
83#define TIS_STS_VALID (1 << 7) /* 0x80 */
84#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
85#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
86#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
87#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
88#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
89
90#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
91#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
92#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
93#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
94#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
95#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
96#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
97
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070098/*
99 * Error value returned if a tpm register does not enter the expected state
100 * after continuous polling. No actual TPM register reading ever returns ~0,
101 * so this value is a safe error indication to be mixed with possible status
102 * register values.
103 */
104#define TPM_TIMEOUT_ERR (~0)
105
106/* Error value returned on various TPM driver errors */
107#define TPM_DRIVER_ERR (~0)
108
109 /* 1 second is plenty for anything TPM does.*/
110#define MAX_DELAY_US (1000 * 1000)
111
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700112/*
113 * Structures defined below allow creating descriptions of TPM vendor/device
114 * ID information for run time discovery. The only device the system knows
115 * about at this time is Infineon slb9635
116 */
117struct device_name {
118 u16 dev_id;
119 const char * const dev_name;
120};
121
122struct vendor_name {
123 u16 vendor_id;
124 const char * vendor_name;
Stefan Reinauerc668af72011-10-27 21:28:25 +0000125 const struct device_name* dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700126};
127
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700128static const struct device_name atmel_devices[] = {
129 {0x3204, "AT97SC3204"},
130 {0xffff}
131};
132
Stefan Reinauerc668af72011-10-27 21:28:25 +0000133static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700134 {0x000b, "SLB9635 TT 1.2"},
135 {0xffff}
136};
137
138static const struct device_name nuvoton_devices[] = {
139 {0x00fe, "NPCT420AA V2"},
140 {0xffff}
141};
142
143static const struct device_name stmicro_devices[] = {
144 {0x0000, "ST33ZP24" },
145 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700146};
147
148static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700149 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700150 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700151 {0x1050, "Nuvoton", nuvoton_devices},
152 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700153};
154
155/*
156 * Cached vendor/device ID pair to indicate that the device has been already
157 * discovered
158 */
Stefan Reinauerc668af72011-10-27 21:28:25 +0000159static u32 vendor_dev_id CAR_GLOBAL;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700160
Aaron Durbinc4220022013-07-24 16:02:14 -0500161static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700162{
Aaron Durbinc4220022013-07-24 16:02:14 -0500163 u8 value = readb(TIS_REG(locality, TIS_REG_STS));
164 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700165 return value;
166}
167
Aaron Durbinc4220022013-07-24 16:02:14 -0500168static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700169{
Aaron Durbinc4220022013-07-24 16:02:14 -0500170 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
171 writeb(sts, TIS_REG(locality, TIS_REG_STS));
172}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700173
Aaron Durbinc4220022013-07-24 16:02:14 -0500174static inline u8 tpm_read_data(int locality)
175{
176 u8 value = readb(TIS_REG(locality, TIS_REG_DATA_FIFO));
177 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
178 return value;
179}
180
181static inline void tpm_write_data(u8 data, int locality)
182{
183 TPM_DEBUG_IO_WRITE(TIS_REG_STS, data);
184 writeb(data, TIS_REG(locality, TIS_REG_DATA_FIFO));
185}
186
187static inline u16 tpm_read_burst_count(int locality)
188{
189 u16 count;
190 count = readb(TIS_REG(locality, TIS_REG_BURST_COUNT));
191 count |= readb(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
192 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
193 return count;
194}
195
196static inline u8 tpm_read_access(int locality)
197{
198 u8 value = readb(TIS_REG(locality, TIS_REG_ACCESS));
199 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
200 return value;
201}
202
203static inline void tpm_write_access(u8 data, int locality)
204{
205 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
206 writeb(data, TIS_REG(locality, TIS_REG_ACCESS));
207}
208
209static inline u32 tpm_read_did_vid(int locality)
210{
211 u32 value = readl(TIS_REG(locality, TIS_REG_DID_VID));
212 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
213 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700214}
215
216/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500217 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700218 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500219 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700220 * expected state. Normally the transition happens within microseconds.
221 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700222 * @locality - locality
223 * @mask - bitmask for the bitfield(s) to watch
224 * @expected - value the field(s) are supposed to be set to
225 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500226 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700227 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500228static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700229{
230 u32 time_us = MAX_DELAY_US;
231 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500232 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700233 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500234 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700235 udelay(1); /* 1 us */
236 time_us--;
237 }
238 return TPM_TIMEOUT_ERR;
239}
240
Aaron Durbinc4220022013-07-24 16:02:14 -0500241static inline int tis_wait_ready(int locality)
242{
243 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
244 TIS_STS_COMMAND_READY);
245}
246
247static inline int tis_wait_valid(int locality)
248{
249 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
250}
251
252static inline int tis_wait_valid_data(int locality)
253{
254 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
255 return tis_wait_sts(locality, has_data, has_data);
256}
257
258static inline int tis_has_valid_data(int locality)
259{
260 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
261 return (tpm_read_status(locality) & has_data) == has_data;
262}
263
264static inline int tis_expect_data(int locality)
265{
266 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
267}
268
269/*
270 * tis_wait_access()
271 *
272 * Wait for at least a second for a access to change its state to match the
273 * expected state. Normally the transition happens within microseconds.
274 *
275 * @locality - locality
276 * @mask - bitmask for the bitfield(s) to watch
277 * @expected - value the field(s) are supposed to be set to
278 *
279 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
280 */
281static int tis_wait_access(int locality, u8 mask, u8 expected)
282{
283 u32 time_us = MAX_DELAY_US;
284 while (time_us > 0) {
285 u8 value = tpm_read_access(locality);
286 if ((value & mask) == expected)
287 return 0;
288 udelay(1); /* 1 us */
289 time_us--;
290 }
291 return TPM_TIMEOUT_ERR;
292}
293
294static inline int tis_wait_dropped_access(int locality)
295{
296 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
297}
298
299static inline int tis_wait_received_access(int locality)
300{
301 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
302 TIS_ACCESS_ACTIVE_LOCALITY);
303}
304
305static inline int tis_has_access(int locality)
306{
307 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
308}
309
310static inline void tis_request_access(int locality)
311{
312 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
313}
314
315static inline void tis_drop_access(int locality)
316{
317 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
318}
319
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700320/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700321 * PC Client Specific TPM Interface Specification section 11.2.12:
322 *
323 * Software must be prepared to send two writes of a "1" to command ready
324 * field: the first to indicate successful read of all the data, thus
325 * clearing the data from the ReadFIFO and freeing the TPM's resources,
326 * and the second to indicate to the TPM it is about to send a new command.
327 *
328 * In practice not all TPMs behave the same so it is necessary to be
329 * flexible when trying to set command ready.
330 *
331 * Returns 0 on success if the TPM is ready for transactions.
332 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
333 */
334static int tis_command_ready(u8 locality)
335{
336 u32 status;
337
338 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500339 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700340
341 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500342 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700343
344 /* Check if command ready is set yet */
345 if (status & TIS_STS_COMMAND_READY)
346 return 0;
347
348 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500349 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700350
Aaron Durbinc4220022013-07-24 16:02:14 -0500351 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700352}
353
354/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700355 * Probe the TPM device and try determining its manufacturer/device name.
356 *
357 * Returns 0 on success (the device is found or was found during an earlier
358 * invocation) or TPM_DRIVER_ERR if the device is not found.
359 */
360static u32 tis_probe(void)
361{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700362 const char *device_name = "unknown";
363 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700364 const struct device_name *dev;
365 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700366 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700367 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700368
Aaron Durbincb997d32013-05-10 00:40:56 -0500369 if (car_get_var(vendor_dev_id))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700370 return 0; /* Already probed. */
371
Aaron Durbinc4220022013-07-24 16:02:14 -0500372 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700373 if (!didvid || (didvid == 0xffffffff)) {
374 printf("%s: No TPM device found\n", __FUNCTION__);
375 return TPM_DRIVER_ERR;
376 }
377
Aaron Durbincb997d32013-05-10 00:40:56 -0500378 car_set_var(vendor_dev_id, didvid);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700379
380 vid = didvid & 0xffff;
381 did = (didvid >> 16) & 0xffff;
382 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
383 int j = 0;
384 u16 known_did;
385 if (vid == vendor_names[i].vendor_id) {
386 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700387 } else {
388 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700389 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700390 dev = &vendor_names[i].dev_names[j];
391 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700392 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700393 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700394 break;
395 }
396 j++;
397 }
398 break;
399 }
400 /* this will have to be converted into debug printout */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700401 printf("Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700402 return 0;
403}
404
405/*
406 * tis_senddata()
407 *
408 * send the passed in data to the TPM device.
409 *
410 * @data - address of the data to send, byte by byte
411 * @len - length of the data to send
412 *
413 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
414 * not accept the entire command).
415 */
416static u32 tis_senddata(const u8 * const data, u32 len)
417{
418 u32 offset = 0;
419 u16 burst = 0;
420 u32 max_cycles = 0;
421 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700422
Aaron Durbinc4220022013-07-24 16:02:14 -0500423 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700424 printf("%s:%d - failed to get 'command_ready' status\n",
425 __FILE__, __LINE__);
426 return TPM_DRIVER_ERR;
427 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500428 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700429
430 while (1) {
431 unsigned count;
432
433 /* Wait till the device is ready to accept more data. */
434 while (!burst) {
435 if (max_cycles++ == MAX_DELAY_US) {
436 printf("%s:%d failed to feed %d bytes of %d\n",
437 __FILE__, __LINE__, len - offset, len);
438 return TPM_DRIVER_ERR;
439 }
440 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500441 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700442 }
443
444 max_cycles = 0;
445
446 /*
447 * Calculate number of bytes the TPM is ready to accept in one
448 * shot.
449 *
450 * We want to send the last byte outside of the loop (hence
451 * the -1 below) to make sure that the 'expected' status bit
452 * changes to zero exactly after the last byte is fed into the
453 * FIFO.
454 */
455 count = min(burst, len - offset - 1);
456 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500457 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700458
Aaron Durbinc4220022013-07-24 16:02:14 -0500459 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700460 printf("%s:%d TPM command feed overflow\n",
461 __FILE__, __LINE__);
462 return TPM_DRIVER_ERR;
463 }
464
Aaron Durbinc4220022013-07-24 16:02:14 -0500465 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700466 if ((offset == (len - 1)) && burst)
467 /*
468 * We need to be able to send the last byte to the
469 * device, so burst size must be nonzero before we
470 * break out.
471 */
472 break;
473 }
474
475 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500476 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700477
478 /*
479 * Verify that TPM does not expect any more data as part of this
480 * command.
481 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500482 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700483 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500484 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700485 return TPM_DRIVER_ERR;
486 }
487
488 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500489 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700490
491 return 0;
492}
493
494/*
495 * tis_readresponse()
496 *
497 * read the TPM device response after a command was issued.
498 *
499 * @buffer - address where to read the response, byte by byte.
500 * @len - pointer to the size of buffer
501 *
502 * On success stores the number of received bytes to len and returns 0. On
503 * errors (misformatted TPM data or synchronization problems) returns
504 * TPM_DRIVER_ERR.
505 */
506static u32 tis_readresponse(u8 *buffer, size_t *len)
507{
508 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700509 u32 offset = 0;
510 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700511 u32 expected_count = *len;
512 int max_cycles = 0;
513
514 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500515 if (tis_wait_valid_data(locality)) {
516 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700517 return TPM_DRIVER_ERR;
518 }
519
520 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500521 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700522 if (max_cycles++ == MAX_DELAY_US) {
523 printf("%s:%d TPM stuck on read\n",
524 __FILE__, __LINE__);
525 return TPM_DRIVER_ERR;
526 }
527 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700528 }
529
530 max_cycles = 0;
531
532 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500533 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700534 if (offset == 6) {
535 /*
536 * We got the first six bytes of the reply,
537 * let's figure out how many bytes to expect
538 * total - it is stored as a 4 byte number in
539 * network order, starting with offset 2 into
540 * the body of the reply.
541 */
542 u32 real_length;
543 memcpy(&real_length,
544 buffer + 2,
545 sizeof(real_length));
546 expected_count = be32_to_cpu(real_length);
547
548 if ((expected_count < offset) ||
549 (expected_count > *len)) {
550 printf("%s:%d bad response size %d\n",
551 __FILE__, __LINE__,
552 expected_count);
553 return TPM_DRIVER_ERR;
554 }
555 }
556 }
557
558 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500559 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700560 printf("%s:%d failed to read response\n",
561 __FILE__, __LINE__);
562 return TPM_DRIVER_ERR;
563 }
564
565 if (offset == expected_count)
566 break; /* We got all we need */
567
Aaron Durbinc4220022013-07-24 16:02:14 -0500568 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700569
Aaron Durbinc4220022013-07-24 16:02:14 -0500570 /* * Make sure we indeed read all there was. */
571 if (tis_has_valid_data(locality)) {
572 printf("%s:%d wrong receive status: %x %d bytes left\n",
573 __FILE__, __LINE__, tpm_read_status(locality),
574 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700575 return TPM_DRIVER_ERR;
576 }
577
578 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700579 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
580 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700581
582 *len = offset;
583 return 0;
584}
585
586/*
587 * tis_init()
588 *
589 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
590 * failure (in case device probing did not succeed).
591 */
592int tis_init(void)
593{
594 if (tis_probe())
595 return TPM_DRIVER_ERR;
596 return 0;
597}
598
599/*
600 * tis_open()
601 *
602 * Requests access to locality 0 for the caller. After all commands have been
603 * completed the caller is supposed to call tis_close().
604 *
605 * Returns 0 on success, TPM_DRIVER_ERR on failure.
606 */
607int tis_open(void)
608{
609 u8 locality = 0; /* we use locality zero for everything */
610
611 if (tis_close())
612 return TPM_DRIVER_ERR;
613
614 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500615 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700616
617 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500618 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700619 printf("%s:%d - failed to lock locality %d\n",
620 __FILE__, __LINE__, locality);
621 return TPM_DRIVER_ERR;
622 }
623
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700624 /* Certain TPMs seem to need some delay here or they hang... */
625 udelay(10);
626
627 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
628 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700629
630 return 0;
631}
632
633/*
634 * tis_close()
635 *
Martin Roth56889792013-07-09 21:39:46 -0600636 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700637 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
638 * removal did not succeed).
639 */
640int tis_close(void)
641{
642 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500643 if (tis_has_access(locality)) {
644 tis_drop_access(locality);
645 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700646 printf("%s:%d - failed to release locality %d\n",
647 __FILE__, __LINE__, locality);
648 return TPM_DRIVER_ERR;
649 }
650 }
651 return 0;
652}
653
654/*
655 * tis_sendrecv()
656 *
657 * Send the requested data to the TPM and then try to get its response
658 *
659 * @sendbuf - buffer of the data to send
660 * @send_size size of the data to send
661 * @recvbuf - memory to save the response to
662 * @recv_len - pointer to the size of the response buffer
663 *
664 * Returns 0 on success (and places the number of response bytes at recv_len)
665 * or TPM_DRIVER_ERR on failure.
666 */
667int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
668 uint8_t *recvbuf, size_t *recv_len)
669{
670 if (tis_senddata(sendbuf, send_size)) {
671 printf("%s:%d failed sending data to TPM\n",
672 __FILE__, __LINE__);
673 return TPM_DRIVER_ERR;
674 }
675
676 return tis_readresponse(recvbuf, recv_len);
677}