xref: /openbmc/u-boot/cmd/tpm-common.c (revision 406fd7e2)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 The Chromium OS Authors.
4  */
5 
6 #include <common.h>
7 #include <command.h>
8 #include <dm.h>
9 #include <asm/unaligned.h>
10 #include <linux/string.h>
11 #include <tpm-common.h>
12 #include "tpm-user-utils.h"
13 
14 /**
15  * Print a byte string in hexdecimal format, 16-bytes per line.
16  *
17  * @param data		byte string to be printed
18  * @param count		number of bytes to be printed
19  */
20 void print_byte_string(u8 *data, size_t count)
21 {
22 	int i, print_newline = 0;
23 
24 	for (i = 0; i < count; i++) {
25 		printf(" %02x", data[i]);
26 		print_newline = (i % 16 == 15);
27 		if (print_newline)
28 			putc('\n');
29 	}
30 	/* Avoid duplicated newline at the end */
31 	if (!print_newline)
32 		putc('\n');
33 }
34 
35 /**
36  * Convert a text string of hexdecimal values into a byte string.
37  *
38  * @param bytes		text string of hexdecimal values with no space
39  *			between them
40  * @param data		output buffer for byte string.  The caller has to make
41  *			sure it is large enough for storing the output.  If
42  *			NULL is passed, a large enough buffer will be allocated,
43  *			and the caller must free it.
44  * @param count_ptr	output variable for the length of byte string
45  * @return pointer to output buffer
46  */
47 void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr)
48 {
49 	char byte[3];
50 	size_t count, length;
51 	int i;
52 
53 	if (!bytes)
54 		return NULL;
55 	length = strlen(bytes);
56 	count = length / 2;
57 
58 	if (!data)
59 		data = malloc(count);
60 	if (!data)
61 		return NULL;
62 
63 	byte[2] = '\0';
64 	for (i = 0; i < length; i += 2) {
65 		byte[0] = bytes[i];
66 		byte[1] = bytes[i + 1];
67 		data[i / 2] = (u8)simple_strtoul(byte, NULL, 16);
68 	}
69 
70 	if (count_ptr)
71 		*count_ptr = count;
72 
73 	return data;
74 }
75 
76 /**
77  * report_return_code() - Report any error and return failure or success
78  *
79  * @param return_code	TPM command return code
80  * @return value of enum command_ret_t
81  */
82 int report_return_code(int return_code)
83 {
84 	if (return_code) {
85 		printf("Error: %d\n", return_code);
86 		return CMD_RET_FAILURE;
87 	} else {
88 		return CMD_RET_SUCCESS;
89 	}
90 }
91 
92 /**
93  * Return number of values defined by a type string.
94  *
95  * @param type_str	type string
96  * @return number of values of type string
97  */
98 int type_string_get_num_values(const char *type_str)
99 {
100 	return strlen(type_str);
101 }
102 
103 /**
104  * Return total size of values defined by a type string.
105  *
106  * @param type_str	type string
107  * @return total size of values of type string, or 0 if type string
108  *  contains illegal type character.
109  */
110 size_t type_string_get_space_size(const char *type_str)
111 {
112 	size_t size;
113 
114 	for (size = 0; *type_str; type_str++) {
115 		switch (*type_str) {
116 		case 'b':
117 			size += 1;
118 			break;
119 		case 'w':
120 			size += 2;
121 			break;
122 		case 'd':
123 			size += 4;
124 			break;
125 		default:
126 			return 0;
127 		}
128 	}
129 
130 	return size;
131 }
132 
133 /**
134  * Allocate a buffer large enough to hold values defined by a type
135  * string.  The caller has to free the buffer.
136  *
137  * @param type_str	type string
138  * @param count		pointer for storing size of buffer
139  * @return pointer to buffer or NULL on error
140  */
141 void *type_string_alloc(const char *type_str, u32 *count)
142 {
143 	void *data;
144 	size_t size;
145 
146 	size = type_string_get_space_size(type_str);
147 	if (!size)
148 		return NULL;
149 	data = malloc(size);
150 	if (data)
151 		*count = size;
152 
153 	return data;
154 }
155 
156 /**
157  * Pack values defined by a type string into a buffer.  The buffer must have
158  * large enough space.
159  *
160  * @param type_str	type string
161  * @param values	text strings of values to be packed
162  * @param data		output buffer of values
163  * @return 0 on success, non-0 on error
164  */
165 int type_string_pack(const char *type_str, char * const values[],
166 		     u8 *data)
167 {
168 	size_t offset;
169 	u32 value;
170 
171 	for (offset = 0; *type_str; type_str++, values++) {
172 		value = simple_strtoul(values[0], NULL, 0);
173 		switch (*type_str) {
174 		case 'b':
175 			data[offset] = value;
176 			offset += 1;
177 			break;
178 		case 'w':
179 			put_unaligned_be16(value, data + offset);
180 			offset += 2;
181 			break;
182 		case 'd':
183 			put_unaligned_be32(value, data + offset);
184 			offset += 4;
185 			break;
186 		default:
187 			return -1;
188 		}
189 	}
190 
191 	return 0;
192 }
193 
194 /**
195  * Read values defined by a type string from a buffer, and write these values
196  * to environment variables.
197  *
198  * @param type_str	type string
199  * @param data		input buffer of values
200  * @param vars		names of environment variables
201  * @return 0 on success, non-0 on error
202  */
203 int type_string_write_vars(const char *type_str, u8 *data,
204 			   char * const vars[])
205 {
206 	size_t offset;
207 	u32 value;
208 
209 	for (offset = 0; *type_str; type_str++, vars++) {
210 		switch (*type_str) {
211 		case 'b':
212 			value = data[offset];
213 			offset += 1;
214 			break;
215 		case 'w':
216 			value = get_unaligned_be16(data + offset);
217 			offset += 2;
218 			break;
219 		case 'd':
220 			value = get_unaligned_be32(data + offset);
221 			offset += 4;
222 			break;
223 		default:
224 			return -1;
225 		}
226 		if (env_set_ulong(*vars, value))
227 			return -1;
228 	}
229 
230 	return 0;
231 }
232 
233 int get_tpm(struct udevice **devp)
234 {
235 	int rc;
236 
237 	rc = uclass_first_device_err(UCLASS_TPM, devp);
238 	if (rc) {
239 		printf("Could not find TPM (ret=%d)\n", rc);
240 		return CMD_RET_FAILURE;
241 	}
242 
243 	return 0;
244 }
245 
246 int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
247 {
248 	struct udevice *dev;
249 	char buf[80];
250 	int rc;
251 
252 	rc = get_tpm(&dev);
253 	if (rc)
254 		return rc;
255 	rc = tpm_get_desc(dev, buf, sizeof(buf));
256 	if (rc < 0) {
257 		printf("Couldn't get TPM info (%d)\n", rc);
258 		return CMD_RET_FAILURE;
259 	}
260 	printf("%s\n", buf);
261 
262 	return 0;
263 }
264 
265 int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
266 {
267 	if (argc != 1)
268 		return CMD_RET_USAGE;
269 
270 	return report_return_code(tpm_init());
271 }
272 
273 int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
274 {
275 	cmd_tbl_t *tpm_commands, *cmd;
276 	struct tpm_chip_priv *priv;
277 	struct udevice *dev;
278 	unsigned int size;
279 	int ret;
280 
281 	if (argc < 2)
282 		return CMD_RET_USAGE;
283 
284 	ret = get_tpm(&dev);
285 	if (ret)
286 		return ret;
287 
288 	priv = dev_get_uclass_priv(dev);
289 
290 	/* Below getters return NULL if the desired stack is not built */
291 	switch (priv->version) {
292 	case TPM_V1:
293 		tpm_commands = get_tpm1_commands(&size);
294 		break;
295 	case TPM_V2:
296 		tpm_commands = get_tpm2_commands(&size);
297 		break;
298 	default:
299 		tpm_commands = NULL;
300 	}
301 
302 	if (!tpm_commands)
303 		return CMD_RET_USAGE;
304 
305 	cmd = find_cmd_tbl(argv[1], tpm_commands, size);
306 	if (!cmd)
307 		return CMD_RET_USAGE;
308 
309 	return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
310 }
311