1 /* 2 * Copyright (C) 2013 Guntermann & Drunck, GmbH 3 * 4 * Written by Dirk Eibach <eibach@gdsys.de> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <tpm.h> 11 #include <i2c.h> 12 #include <asm/unaligned.h> 13 14 #define ATMEL_TPM_TIMEOUT_MS 5000 /* sufficient for anything but 15 generating/exporting keys */ 16 17 /* 18 * tis_init() 19 * 20 * Initialize the TPM device. Returns 0 on success or -1 on 21 * failure (in case device probing did not succeed). 22 */ 23 int tis_init(void) 24 { 25 return 0; 26 } 27 28 /* 29 * tis_open() 30 * 31 * Requests access to locality 0 for the caller. After all commands have been 32 * completed the caller is supposed to call tis_close(). 33 * 34 * Returns 0 on success, -1 on failure. 35 */ 36 int tis_open(void) 37 { 38 return 0; 39 } 40 41 /* 42 * tis_close() 43 * 44 * terminate the currect session with the TPM by releasing the locked 45 * locality. Returns 0 on success of -1 on failure (in case lock 46 * removal did not succeed). 47 */ 48 int tis_close(void) 49 { 50 return 0; 51 } 52 53 /* 54 * tis_sendrecv() 55 * 56 * Send the requested data to the TPM and then try to get its response 57 * 58 * @sendbuf - buffer of the data to send 59 * @send_size size of the data to send 60 * @recvbuf - memory to save the response to 61 * @recv_len - pointer to the size of the response buffer 62 * 63 * Returns 0 on success (and places the number of response bytes at recv_len) 64 * or -1 on failure. 65 */ 66 int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, 67 size_t *recv_len) 68 { 69 int res; 70 unsigned long start; 71 72 #ifdef DEBUG 73 memset(recvbuf, 0xcc, *recv_len); 74 printf("send to TPM (%d bytes, recv_len=%d):\n", send_size, *recv_len); 75 print_buffer(0, (void *)sendbuf, 1, send_size, 0); 76 #endif 77 78 res = i2c_write(0x29, 0, 0, (uchar *)sendbuf, send_size); 79 if (res) { 80 printf("i2c_write returned %d\n", res); 81 return -1; 82 } 83 84 start = get_timer(0); 85 while ((res = i2c_read(0x29, 0, 0, recvbuf, 10))) { 86 if (get_timer(start) > ATMEL_TPM_TIMEOUT_MS) { 87 puts("tpm timed out\n"); 88 return -1; 89 } 90 udelay(100); 91 } 92 if (!res) { 93 *recv_len = get_unaligned_be32(recvbuf + 2); 94 if (*recv_len > 10) 95 res = i2c_read(0x29, 0, 0, recvbuf, *recv_len); 96 } 97 if (res) { 98 printf("i2c_read returned %d (rlen=%d)\n", res, *recv_len); 99 #ifdef DEBUG 100 print_buffer(0, recvbuf, 1, *recv_len, 0); 101 #endif 102 } 103 104 #ifdef DEBUG 105 if (!res) { 106 printf("read from TPM (%d bytes):\n", *recv_len); 107 print_buffer(0, recvbuf, 1, *recv_len, 0); 108 } 109 #endif 110 111 return res; 112 } 113