blob: 1cbf80057127363b5a222adbb9cc9a2d1558a700 [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
30/* #define DEBUG */
31#include <stdlib.h>
32#include <string.h>
33#include <delay.h>
34#include <arch/io.h>
35#include <arch/byteorder.h>
36#include <console/console.h>
37#include <pc80/tpm.h>
38
39#ifdef DEBUG
40#define TPM_DEBUG_ON 1
41#else
42#define TPM_DEBUG_ON 0
43#endif
44
45#define PREFIX "lpc_tpm: "
46
47/* coreboot wrapper for TPM driver (start) */
48#define TPM_DEBUG(fmt, args...) \
49 if (TPM_DEBUG_ON) { \
50 printk(BIOS_DEBUG, PREFIX); \
51 printk(BIOS_DEBUG, fmt , ##args); \
52 }
53#define printf(x...) printk(BIOS_ERR, x)
54
55#define min(a,b) MIN(a,b)
56#define max(a,b) MAX(a,b)
57#define readb(_a) (*(volatile unsigned char *) (_a))
58#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v))
59#define readl(_a) (*(volatile unsigned long *) (_a))
60#define writel(_v, _a) (*(volatile unsigned long *) (_a) = (_v))
61/* coreboot wrapper for TPM driver (end) */
62
63#ifndef CONFIG_TPM_TIS_BASE_ADDRESS
64/* Base TPM address standard for x86 systems */
65#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
66#endif
67
68/* the macro accepts the locality value, but only locality 0 is operational */
69#define TIS_REG(LOCALITY, REG) \
70 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
71
72/* hardware registers' offsets */
73#define TIS_REG_ACCESS 0x0
74#define TIS_REG_INT_ENABLE 0x8
75#define TIS_REG_INT_VECTOR 0xc
76#define TIS_REG_INT_STATUS 0x10
77#define TIS_REG_INTF_CAPABILITY 0x14
78#define TIS_REG_STS 0x18
79#define TIS_REG_DATA_FIFO 0x24
80#define TIS_REG_DID_VID 0xf00
81#define TIS_REG_RID 0xf04
82
83/* Some registers' bit field definitions */
84#define TIS_STS_VALID (1 << 7) /* 0x80 */
85#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
86#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
87#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
88#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
89#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
90
91#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
92#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
93#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
94#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
95#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
96#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
97#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
98
99#define TIS_STS_BURST_COUNT_MASK (0xffff)
100#define TIS_STS_BURST_COUNT_SHIFT (8)
101
102/*
103 * Error value returned if a tpm register does not enter the expected state
104 * after continuous polling. No actual TPM register reading ever returns ~0,
105 * so this value is a safe error indication to be mixed with possible status
106 * register values.
107 */
108#define TPM_TIMEOUT_ERR (~0)
109
110/* Error value returned on various TPM driver errors */
111#define TPM_DRIVER_ERR (~0)
112
113 /* 1 second is plenty for anything TPM does.*/
114#define MAX_DELAY_US (1000 * 1000)
115
116/* Retrieve burst count value out of the status register contents. */
117#define BURST_COUNT(status) ((u16)(((status) >> TIS_STS_BURST_COUNT_SHIFT) & \
118 TIS_STS_BURST_COUNT_MASK))
119
120/*
121 * Structures defined below allow creating descriptions of TPM vendor/device
122 * ID information for run time discovery. The only device the system knows
123 * about at this time is Infineon slb9635
124 */
125struct device_name {
126 u16 dev_id;
127 const char * const dev_name;
128};
129
130struct vendor_name {
131 u16 vendor_id;
132 const char * vendor_name;
133 struct device_name* dev_names;
134};
135
136static struct device_name infineon_devices[] = {
137 {0xb, "SLB9635 TT 1.2"},
138 {0}
139};
140
141static const struct vendor_name vendor_names[] = {
142 {0x15d1, "Infineon", infineon_devices},
143};
144
145/*
146 * Cached vendor/device ID pair to indicate that the device has been already
147 * discovered
148 */
149static u32 vendor_dev_id;
150
151static int is_byte_reg(u32 reg)
152{
153 /*
154 * These TPM registers are 8 bits wide and as such require byte access
155 * on writes and truncated value on reads.
156 */
157 return ((reg == TIS_REG_ACCESS) ||
158 (reg == TIS_REG_INT_VECTOR) ||
159 (reg == TIS_REG_DATA_FIFO));
160}
161
162/* TPM access functions are carved out to make tracing easier. */
163static u32 tpm_read(int locality, u32 reg)
164{
165 u32 value;
166 /*
167 * Data FIFO register must be read and written in byte access mode,
168 * otherwise the FIFO values are returned 4 bytes at a time.
169 */
170 if (is_byte_reg(reg))
171 value = readb(TIS_REG(locality, reg));
172 else
173 value = readl(TIS_REG(locality, reg));
174
175 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", reg, value);
176 return value;
177}
178
179static void tpm_write(u32 value, int locality, u32 reg)
180{
181 TPM_DEBUG("Write reg 0x%x with 0x%x\n", reg, value);
182
183 if (is_byte_reg(reg))
184 writeb(value & 0xff, TIS_REG(locality, reg));
185 else
186 writel(value, TIS_REG(locality, reg));
187}
188
189/*
190 * tis_wait_reg()
191 *
192 * Wait for at least a second for a register to change its state to match the
193 * expected state. Normally the transition happens within microseconds.
194 *
195 * @reg - the TPM register offset
196 * @locality - locality
197 * @mask - bitmask for the bitfield(s) to watch
198 * @expected - value the field(s) are supposed to be set to
199 *
200 * Returns the register contents in case the expected value was found in the
201 * appropriate register bits, or TPM_TIMEOUT_ERR on timeout.
202 */
203static u32 tis_wait_reg(u8 reg, u8 locality, u8 mask, u8 expected)
204{
205 u32 time_us = MAX_DELAY_US;
206 while (time_us > 0) {
207 u32 value = tpm_read(locality, reg);
208 if ((value & mask) == expected)
209 return value;
210 udelay(1); /* 1 us */
211 time_us--;
212 }
213 return TPM_TIMEOUT_ERR;
214}
215
216/*
217 * Probe the TPM device and try determining its manufacturer/device name.
218 *
219 * Returns 0 on success (the device is found or was found during an earlier
220 * invocation) or TPM_DRIVER_ERR if the device is not found.
221 */
222static u32 tis_probe(void)
223{
224 u32 didvid = tpm_read(0, TIS_REG_DID_VID);
225 int i;
226 const char *device_name = "unknown";
227 const char *vendor_name = device_name;
228 u16 vid, did;
229
230 if (vendor_dev_id)
231 return 0; /* Already probed. */
232
233 if (!didvid || (didvid == 0xffffffff)) {
234 printf("%s: No TPM device found\n", __FUNCTION__);
235 return TPM_DRIVER_ERR;
236 }
237
238 vendor_dev_id = didvid;
239
240 vid = didvid & 0xffff;
241 did = (didvid >> 16) & 0xffff;
242 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
243 int j = 0;
244 u16 known_did;
245 if (vid == vendor_names[i].vendor_id) {
246 vendor_name = vendor_names[i].vendor_name;
247 }
248 while ((known_did = vendor_names[i].dev_names[j].dev_id) != 0) {
249 if (known_did == did) {
250 device_name =
251 vendor_names[i].dev_names[j].dev_name;
252 break;
253 }
254 j++;
255 }
256 break;
257 }
258 /* this will have to be converted into debug printout */
259 TPM_DEBUG("Found TPM %s by %s\n", device_name, vendor_name);
260 return 0;
261}
262
263/*
264 * tis_senddata()
265 *
266 * send the passed in data to the TPM device.
267 *
268 * @data - address of the data to send, byte by byte
269 * @len - length of the data to send
270 *
271 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
272 * not accept the entire command).
273 */
274static u32 tis_senddata(const u8 * const data, u32 len)
275{
276 u32 offset = 0;
277 u16 burst = 0;
278 u32 max_cycles = 0;
279 u8 locality = 0;
280 u32 value;
281
282 value = tis_wait_reg(TIS_REG_STS, locality, TIS_STS_COMMAND_READY,
283 TIS_STS_COMMAND_READY);
284 if (value == TPM_TIMEOUT_ERR) {
285 printf("%s:%d - failed to get 'command_ready' status\n",
286 __FILE__, __LINE__);
287 return TPM_DRIVER_ERR;
288 }
289 burst = BURST_COUNT(value);
290
291 while (1) {
292 unsigned count;
293
294 /* Wait till the device is ready to accept more data. */
295 while (!burst) {
296 if (max_cycles++ == MAX_DELAY_US) {
297 printf("%s:%d failed to feed %d bytes of %d\n",
298 __FILE__, __LINE__, len - offset, len);
299 return TPM_DRIVER_ERR;
300 }
301 udelay(1);
302 burst = BURST_COUNT(tpm_read(locality, TIS_REG_STS));
303 }
304
305 max_cycles = 0;
306
307 /*
308 * Calculate number of bytes the TPM is ready to accept in one
309 * shot.
310 *
311 * We want to send the last byte outside of the loop (hence
312 * the -1 below) to make sure that the 'expected' status bit
313 * changes to zero exactly after the last byte is fed into the
314 * FIFO.
315 */
316 count = min(burst, len - offset - 1);
317 while (count--)
318 tpm_write(data[offset++], locality, TIS_REG_DATA_FIFO);
319
320 value = tis_wait_reg(TIS_REG_STS, locality,
321 TIS_STS_VALID, TIS_STS_VALID);
322
323 if ((value == TPM_TIMEOUT_ERR) || !(value & TIS_STS_EXPECT)) {
324 printf("%s:%d TPM command feed overflow\n",
325 __FILE__, __LINE__);
326 return TPM_DRIVER_ERR;
327 }
328
329 burst = BURST_COUNT(value);
330 if ((offset == (len - 1)) && burst)
331 /*
332 * We need to be able to send the last byte to the
333 * device, so burst size must be nonzero before we
334 * break out.
335 */
336 break;
337 }
338
339 /* Send the last byte. */
340 tpm_write(data[offset++], locality, TIS_REG_DATA_FIFO);
341
342 /*
343 * Verify that TPM does not expect any more data as part of this
344 * command.
345 */
346 value = tis_wait_reg(TIS_REG_STS, locality,
347 TIS_STS_VALID, TIS_STS_VALID);
348 if ((value == TPM_TIMEOUT_ERR) || (value & TIS_STS_EXPECT)) {
349 printf("%s:%d unexpected TPM status 0x%x\n",
350 __FILE__, __LINE__, value);
351 return TPM_DRIVER_ERR;
352 }
353
354 /* OK, sitting pretty, let's start the command execution. */
355 tpm_write(TIS_STS_TPM_GO, locality, TIS_REG_STS);
356
357 return 0;
358}
359
360/*
361 * tis_readresponse()
362 *
363 * read the TPM device response after a command was issued.
364 *
365 * @buffer - address where to read the response, byte by byte.
366 * @len - pointer to the size of buffer
367 *
368 * On success stores the number of received bytes to len and returns 0. On
369 * errors (misformatted TPM data or synchronization problems) returns
370 * TPM_DRIVER_ERR.
371 */
372static u32 tis_readresponse(u8 *buffer, size_t *len)
373{
374 u16 burst_count;
375 u32 status;
376 u32 offset = 0;
377 u8 locality = 0;
378 const u32 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
379 u32 expected_count = *len;
380 int max_cycles = 0;
381
382 /* Wait for the TPM to process the command */
383 status = tis_wait_reg(TIS_REG_STS, locality, has_data, has_data);
384 if (status == TPM_TIMEOUT_ERR) {
385 printf("%s:%d failed processing command\n",
386 __FILE__, __LINE__);
387 return TPM_DRIVER_ERR;
388 }
389
390 do {
391 while ((burst_count = BURST_COUNT(status)) == 0) {
392 if (max_cycles++ == MAX_DELAY_US) {
393 printf("%s:%d TPM stuck on read\n",
394 __FILE__, __LINE__);
395 return TPM_DRIVER_ERR;
396 }
397 udelay(1);
398 status = tpm_read(locality, TIS_REG_STS);
399 }
400
401 max_cycles = 0;
402
403 while (burst_count-- && (offset < expected_count)) {
404 buffer[offset++] = (u8) tpm_read(locality,
405 TIS_REG_DATA_FIFO);
406 if (offset == 6) {
407 /*
408 * We got the first six bytes of the reply,
409 * let's figure out how many bytes to expect
410 * total - it is stored as a 4 byte number in
411 * network order, starting with offset 2 into
412 * the body of the reply.
413 */
414 u32 real_length;
415 memcpy(&real_length,
416 buffer + 2,
417 sizeof(real_length));
418 expected_count = be32_to_cpu(real_length);
419
420 if ((expected_count < offset) ||
421 (expected_count > *len)) {
422 printf("%s:%d bad response size %d\n",
423 __FILE__, __LINE__,
424 expected_count);
425 return TPM_DRIVER_ERR;
426 }
427 }
428 }
429
430 /* Wait for the next portion */
431 status = tis_wait_reg(TIS_REG_STS, locality,
432 TIS_STS_VALID, TIS_STS_VALID);
433 if (status == TPM_TIMEOUT_ERR) {
434 printf("%s:%d failed to read response\n",
435 __FILE__, __LINE__);
436 return TPM_DRIVER_ERR;
437 }
438
439 if (offset == expected_count)
440 break; /* We got all we need */
441
442 } while ((status & has_data) == has_data);
443
444 /*
445 * Make sure we indeed read all there was. The TIS_STS_VALID bit is
446 * known to be set.
447 */
448 if (status & TIS_STS_DATA_AVAILABLE) {
449 printf("%s:%d wrong receive status %x\n",
450 __FILE__, __LINE__, status);
451 return TPM_DRIVER_ERR;
452 }
453
454 /* Tell the TPM that we are done. */
455 tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
456
457 *len = offset;
458 return 0;
459}
460
461/*
462 * tis_init()
463 *
464 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
465 * failure (in case device probing did not succeed).
466 */
467int tis_init(void)
468{
469 if (tis_probe())
470 return TPM_DRIVER_ERR;
471 return 0;
472}
473
474/*
475 * tis_open()
476 *
477 * Requests access to locality 0 for the caller. After all commands have been
478 * completed the caller is supposed to call tis_close().
479 *
480 * Returns 0 on success, TPM_DRIVER_ERR on failure.
481 */
482int tis_open(void)
483{
484 u8 locality = 0; /* we use locality zero for everything */
485
486 if (tis_close())
487 return TPM_DRIVER_ERR;
488
489 /* now request access to locality */
490 tpm_write(TIS_ACCESS_REQUEST_USE, locality, TIS_REG_ACCESS);
491
492 /* did we get a lock? */
493 if (tis_wait_reg(TIS_REG_ACCESS, locality,
494 TIS_ACCESS_ACTIVE_LOCALITY,
495 TIS_ACCESS_ACTIVE_LOCALITY) == TPM_TIMEOUT_ERR) {
496 printf("%s:%d - failed to lock locality %d\n",
497 __FILE__, __LINE__, locality);
498 return TPM_DRIVER_ERR;
499 }
500
501 tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
502
503 return 0;
504}
505
506/*
507 * tis_close()
508 *
509 * terminate the currect session with the TPM by releasing the locked
510 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
511 * removal did not succeed).
512 */
513int tis_close(void)
514{
515 u8 locality = 0;
516 if (tpm_read(locality, TIS_REG_ACCESS) &
517 TIS_ACCESS_ACTIVE_LOCALITY) {
518 tpm_write(TIS_ACCESS_ACTIVE_LOCALITY, locality, TIS_REG_ACCESS);
519
520 if (tis_wait_reg(TIS_REG_ACCESS, locality,
521 TIS_ACCESS_ACTIVE_LOCALITY, 0) ==
522 TPM_TIMEOUT_ERR) {
523 printf("%s:%d - failed to release locality %d\n",
524 __FILE__, __LINE__, locality);
525 return TPM_DRIVER_ERR;
526 }
527 }
528 return 0;
529}
530
531/*
532 * tis_sendrecv()
533 *
534 * Send the requested data to the TPM and then try to get its response
535 *
536 * @sendbuf - buffer of the data to send
537 * @send_size size of the data to send
538 * @recvbuf - memory to save the response to
539 * @recv_len - pointer to the size of the response buffer
540 *
541 * Returns 0 on success (and places the number of response bytes at recv_len)
542 * or TPM_DRIVER_ERR on failure.
543 */
544int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
545 uint8_t *recvbuf, size_t *recv_len)
546{
547 if (tis_senddata(sendbuf, send_size)) {
548 printf("%s:%d failed sending data to TPM\n",
549 __FILE__, __LINE__);
550 return TPM_DRIVER_ERR;
551 }
552
553 return tis_readresponse(recvbuf, recv_len);
554}