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