Blame view

lib/tpm-common.c 3.73 KB
d677bfe2f   Miquel Raynal   tpm: disociate TP...
1
2
3
4
5
  // SPDX-License-Identifier: GPL-2.0+
  /*
   * Copyright (c) 2013 The Chromium OS Authors.
   * Coypright (c) 2013 Guntermann & Drunck GmbH
   */
34a5e8a2f   Simon Glass   tpm: Tidy up logg...
6
  #define LOG_CATEGORY UCLASS_TPM
d677bfe2f   Miquel Raynal   tpm: disociate TP...
7
8
9
10
11
  #include <common.h>
  #include <dm.h>
  #include <asm/unaligned.h>
  #include <tpm-common.h>
  #include "tpm-utils.h"
0a60a0a65   Simon Glass   tpm: Remove use o...
12
13
14
15
16
17
  enum tpm_version tpm_get_version(struct udevice *dev)
  {
  	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
  
  	return priv->version;
  }
d677bfe2f   Miquel Raynal   tpm: disociate TP...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  int pack_byte_string(u8 *str, size_t size, const char *format, ...)
  {
  	va_list args;
  	size_t offset = 0, length = 0;
  	u8 *data = NULL;
  	u32 value = 0;
  
  	va_start(args, format);
  	for (; *format; format++) {
  		switch (*format) {
  		case 'b':
  			offset = va_arg(args, size_t);
  			value = va_arg(args, int);
  			length = 1;
  			break;
  		case 'w':
  			offset = va_arg(args, size_t);
  			value = va_arg(args, int);
  			length = 2;
  			break;
  		case 'd':
  			offset = va_arg(args, size_t);
  			value = va_arg(args, u32);
  			length = 4;
  			break;
  		case 's':
  			offset = va_arg(args, size_t);
  			data = va_arg(args, u8 *);
  			length = va_arg(args, u32);
  			break;
  		default:
  			debug("Couldn't recognize format string
  ");
  			va_end(args);
  			return -1;
  		}
  
  		if (offset + length > size) {
  			va_end(args);
  			return -1;
  		}
  
  		switch (*format) {
  		case 'b':
  			str[offset] = value;
  			break;
  		case 'w':
  			put_unaligned_be16(value, str + offset);
  			break;
  		case 'd':
  			put_unaligned_be32(value, str + offset);
  			break;
  		case 's':
  			memcpy(str + offset, data, length);
  			break;
  		}
  	}
  	va_end(args);
  
  	return 0;
  }
  
  int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
  {
  	va_list args;
  	size_t offset = 0, length = 0;
  	u8 *ptr8 = NULL;
  	u16 *ptr16 = NULL;
  	u32 *ptr32 = NULL;
  
  	va_start(args, format);
  	for (; *format; format++) {
  		switch (*format) {
  		case 'b':
  			offset = va_arg(args, size_t);
  			ptr8 = va_arg(args, u8 *);
  			length = 1;
  			break;
  		case 'w':
  			offset = va_arg(args, size_t);
  			ptr16 = va_arg(args, u16 *);
  			length = 2;
  			break;
  		case 'd':
  			offset = va_arg(args, size_t);
  			ptr32 = va_arg(args, u32 *);
  			length = 4;
  			break;
  		case 's':
  			offset = va_arg(args, size_t);
  			ptr8 = va_arg(args, u8 *);
  			length = va_arg(args, u32);
  			break;
  		default:
  			va_end(args);
  			debug("Couldn't recognize format string
  ");
  			return -1;
  		}
  
  		if (offset + length > size) {
  			va_end(args);
5092af6b5   Simon Glass   tpm: Fix a loggin...
120
121
  			log_err("Failed to read: size=%zd, offset=%zx, len=%zx
  ",
34a5e8a2f   Simon Glass   tpm: Tidy up logg...
122
  				size, offset, length);
d677bfe2f   Miquel Raynal   tpm: disociate TP...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  			return -1;
  		}
  
  		switch (*format) {
  		case 'b':
  			*ptr8 = str[offset];
  			break;
  		case 'w':
  			*ptr16 = get_unaligned_be16(str + offset);
  			break;
  		case 'd':
  			*ptr32 = get_unaligned_be32(str + offset);
  			break;
  		case 's':
  			memcpy(ptr8, str + offset, length);
  			break;
  		}
  	}
  	va_end(args);
  
  	return 0;
  }
  
  u32 tpm_command_size(const void *command)
  {
  	const size_t command_size_offset = 2;
  
  	return get_unaligned_be32(command + command_size_offset);
  }
  
  u32 tpm_return_code(const void *response)
  {
  	const size_t return_code_offset = 6;
  
  	return get_unaligned_be32(response + return_code_offset);
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
159
160
  u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
  			 void *response, size_t *size_ptr)
d677bfe2f   Miquel Raynal   tpm: disociate TP...
161
  {
d677bfe2f   Miquel Raynal   tpm: disociate TP...
162
163
164
  	int err, ret;
  	u8 response_buffer[COMMAND_BUFFER_SIZE];
  	size_t response_length;
aa643013e   Miquel Raynal   tpm: add possible...
165
  	int i;
d677bfe2f   Miquel Raynal   tpm: disociate TP...
166
167
168
169
170
171
172
  
  	if (response) {
  		response_length = *size_ptr;
  	} else {
  		response = response_buffer;
  		response_length = sizeof(response_buffer);
  	}
d677bfe2f   Miquel Raynal   tpm: disociate TP...
173
174
175
176
  	err = tpm_xfer(dev, command, tpm_command_size(command),
  		       response, &response_length);
  
  	if (err < 0)
bcdf6b9f2   Miquel Raynal   tpm: report drive...
177
  		return err;
d677bfe2f   Miquel Raynal   tpm: disociate TP...
178
179
  	if (size_ptr)
  		*size_ptr = response_length;
aa643013e   Miquel Raynal   tpm: add possible...
180
  	ret = tpm_return_code(response);
34a5e8a2f   Simon Glass   tpm: Tidy up logg...
181
  	log_debug("TPM response [ret:%d]: ", ret);
aa643013e   Miquel Raynal   tpm: add possible...
182
  	for (i = 0; i < response_length; i++)
34a5e8a2f   Simon Glass   tpm: Tidy up logg...
183
184
185
  		log_debug("%02x ", ((u8 *)response)[i]);
  	log_debug("
  ");
aa643013e   Miquel Raynal   tpm: add possible...
186
187
  
  	return ret;
d677bfe2f   Miquel Raynal   tpm: disociate TP...
188
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
189
  int tpm_init(struct udevice *dev)
d677bfe2f   Miquel Raynal   tpm: disociate TP...
190
  {
d677bfe2f   Miquel Raynal   tpm: disociate TP...
191
192
  	return tpm_open(dev);
  }