xref: /openbmc/u-boot/cmd/tpm-common.c (revision d7869cec072d613a4b9ee7e7432e295155d372f3)
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 <environment.h>
10  #include <malloc.h>
11  #include <asm/unaligned.h>
12  #include <linux/string.h>
13  #include <tpm-common.h>
14  #include "tpm-user-utils.h"
15  
16  static struct udevice *tpm_dev;
17  
18  /**
19   * Print a byte string in hexdecimal format, 16-bytes per line.
20   *
21   * @param data		byte string to be printed
22   * @param count		number of bytes to be printed
23   */
print_byte_string(u8 * data,size_t count)24  void print_byte_string(u8 *data, size_t count)
25  {
26  	int i, print_newline = 0;
27  
28  	for (i = 0; i < count; i++) {
29  		printf(" %02x", data[i]);
30  		print_newline = (i % 16 == 15);
31  		if (print_newline)
32  			putc('\n');
33  	}
34  	/* Avoid duplicated newline at the end */
35  	if (!print_newline)
36  		putc('\n');
37  }
38  
39  /**
40   * Convert a text string of hexdecimal values into a byte string.
41   *
42   * @param bytes		text string of hexdecimal values with no space
43   *			between them
44   * @param data		output buffer for byte string.  The caller has to make
45   *			sure it is large enough for storing the output.  If
46   *			NULL is passed, a large enough buffer will be allocated,
47   *			and the caller must free it.
48   * @param count_ptr	output variable for the length of byte string
49   * Return: pointer to output buffer
50   */
parse_byte_string(char * bytes,u8 * data,size_t * count_ptr)51  void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr)
52  {
53  	char byte[3];
54  	size_t count, length;
55  	int i;
56  
57  	if (!bytes)
58  		return NULL;
59  	length = strlen(bytes);
60  	count = length / 2;
61  
62  	if (!data)
63  		data = malloc(count);
64  	if (!data)
65  		return NULL;
66  
67  	byte[2] = '\0';
68  	for (i = 0; i < length; i += 2) {
69  		byte[0] = bytes[i];
70  		byte[1] = bytes[i + 1];
71  		data[i / 2] = (u8)simple_strtoul(byte, NULL, 16);
72  	}
73  
74  	if (count_ptr)
75  		*count_ptr = count;
76  
77  	return data;
78  }
79  
80  /**
81   * report_return_code() - Report any error and return failure or success
82   *
83   * @param return_code	TPM command return code
84   * Return: value of enum command_ret_t
85   */
report_return_code(int return_code)86  int report_return_code(int return_code)
87  {
88  	if (return_code) {
89  		printf("Error: %d\n", return_code);
90  		return CMD_RET_FAILURE;
91  	} else {
92  		return CMD_RET_SUCCESS;
93  	}
94  }
95  
96  /**
97   * Return number of values defined by a type string.
98   *
99   * @param type_str	type string
100   * Return: number of values of type string
101   */
type_string_get_num_values(const char * type_str)102  int type_string_get_num_values(const char *type_str)
103  {
104  	return strlen(type_str);
105  }
106  
107  /**
108   * Return total size of values defined by a type string.
109   *
110   * @param type_str	type string
111   * Return: total size of values of type string, or 0 if type string
112   *  contains illegal type character.
113   */
type_string_get_space_size(const char * type_str)114  size_t type_string_get_space_size(const char *type_str)
115  {
116  	size_t size;
117  
118  	for (size = 0; *type_str; type_str++) {
119  		switch (*type_str) {
120  		case 'b':
121  			size += 1;
122  			break;
123  		case 'w':
124  			size += 2;
125  			break;
126  		case 'd':
127  			size += 4;
128  			break;
129  		default:
130  			return 0;
131  		}
132  	}
133  
134  	return size;
135  }
136  
137  /**
138   * Allocate a buffer large enough to hold values defined by a type
139   * string.  The caller has to free the buffer.
140   *
141   * @param type_str	type string
142   * @param count		pointer for storing size of buffer
143   * Return: pointer to buffer or NULL on error
144   */
type_string_alloc(const char * type_str,u32 * count)145  void *type_string_alloc(const char *type_str, u32 *count)
146  {
147  	void *data;
148  	size_t size;
149  
150  	size = type_string_get_space_size(type_str);
151  	if (!size)
152  		return NULL;
153  	data = malloc(size);
154  	if (data)
155  		*count = size;
156  
157  	return data;
158  }
159  
160  /**
161   * Pack values defined by a type string into a buffer.  The buffer must have
162   * large enough space.
163   *
164   * @param type_str	type string
165   * @param values	text strings of values to be packed
166   * @param data		output buffer of values
167   * Return: 0 on success, non-0 on error
168   */
type_string_pack(const char * type_str,char * const values[],u8 * data)169  int type_string_pack(const char *type_str, char * const values[],
170  		     u8 *data)
171  {
172  	size_t offset;
173  	u32 value;
174  
175  	for (offset = 0; *type_str; type_str++, values++) {
176  		value = simple_strtoul(values[0], NULL, 0);
177  		switch (*type_str) {
178  		case 'b':
179  			data[offset] = value;
180  			offset += 1;
181  			break;
182  		case 'w':
183  			put_unaligned_be16(value, data + offset);
184  			offset += 2;
185  			break;
186  		case 'd':
187  			put_unaligned_be32(value, data + offset);
188  			offset += 4;
189  			break;
190  		default:
191  			return -1;
192  		}
193  	}
194  
195  	return 0;
196  }
197  
198  /**
199   * Read values defined by a type string from a buffer, and write these values
200   * to environment variables.
201   *
202   * @param type_str	type string
203   * @param data		input buffer of values
204   * @param vars		names of environment variables
205   * Return: 0 on success, non-0 on error
206   */
type_string_write_vars(const char * type_str,u8 * data,char * const vars[])207  int type_string_write_vars(const char *type_str, u8 *data,
208  			   char * const vars[])
209  {
210  	size_t offset;
211  	u32 value;
212  
213  	for (offset = 0; *type_str; type_str++, vars++) {
214  		switch (*type_str) {
215  		case 'b':
216  			value = data[offset];
217  			offset += 1;
218  			break;
219  		case 'w':
220  			value = get_unaligned_be16(data + offset);
221  			offset += 2;
222  			break;
223  		case 'd':
224  			value = get_unaligned_be32(data + offset);
225  			offset += 4;
226  			break;
227  		default:
228  			return -1;
229  		}
230  		if (env_set_ulong(*vars, value))
231  			return -1;
232  	}
233  
234  	return 0;
235  }
236  
tpm_show_device(void)237  static int tpm_show_device(void)
238  {
239  	struct udevice *dev;
240  	char buf[80];
241  	int n = 0, rc;
242  
243  	for_each_tpm_device(dev) {
244  		rc = tpm_get_desc(dev, buf, sizeof(buf));
245  		if (rc < 0)
246  			printf("device %d: can't get info\n", n);
247  		else
248  			printf("device %d: %s\n", n, buf);
249  
250  		n++;
251  	};
252  
253  	return 0;
254  }
255  
tpm_set_device(unsigned long num)256  static int tpm_set_device(unsigned long num)
257  {
258  	struct udevice *dev;
259  	unsigned long n = 0;
260  	int rc = CMD_RET_FAILURE;
261  
262  	for_each_tpm_device(dev) {
263  		if (n == num) {
264  			rc = 0;
265  			break;
266  		}
267  
268  		n++;
269  	}
270  
271  	if (!rc)
272  		tpm_dev = dev;
273  
274  	return rc;
275  }
276  
get_tpm(struct udevice ** devp)277  int get_tpm(struct udevice **devp)
278  {
279  	int rc;
280  
281  	/*
282  	 * To keep a backward compatibility with previous code,
283  	 * if a tpm device is not explicitly set, we set the first one.
284  	 */
285  	if (!tpm_dev) {
286  		rc = tpm_set_device(0);
287  		if (rc) {
288  			printf("Couldn't set TPM 0 (rc = %d)\n", rc);
289  			return CMD_RET_FAILURE;
290  		}
291  	}
292  
293  	if (devp)
294  		*devp = tpm_dev;
295  
296  	return 0;
297  }
298  
do_tpm_device(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])299  int do_tpm_device(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
300  {
301  	unsigned long num;
302  	int rc;
303  
304  	if (argc == 2) {
305  		num = simple_strtoul(argv[1], NULL, 10);
306  
307  		rc = tpm_set_device(num);
308  		if (rc)
309  			printf("Couldn't set TPM %lu (rc = %d)\n", num, rc);
310  	} else {
311  		rc = tpm_show_device();
312  	}
313  
314  	return rc;
315  }
316  
do_tpm_info(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])317  int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
318  {
319  	struct udevice *dev;
320  	char buf[80];
321  	int rc;
322  
323  	rc = get_tpm(&dev);
324  	if (rc)
325  		return rc;
326  	rc = tpm_get_desc(dev, buf, sizeof(buf));
327  	if (rc < 0) {
328  		printf("Couldn't get TPM info (%d)\n", rc);
329  		return CMD_RET_FAILURE;
330  	}
331  	printf("%s\n", buf);
332  
333  	return 0;
334  }
335  
do_tpm_report_state(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])336  int do_tpm_report_state(cmd_tbl_t *cmdtp, int flag, int argc,
337  			char *const argv[])
338  {
339  	struct udevice *dev;
340  	char buf[80];
341  	int rc;
342  
343  	rc = get_tpm(&dev);
344  	if (rc)
345  		return rc;
346  	rc = tpm_report_state(dev, buf, sizeof(buf));
347  	if (rc < 0) {
348  		printf("Couldn't get TPM state (%d)\n", rc);
349  		return CMD_RET_FAILURE;
350  	}
351  	printf("%s\n", buf);
352  
353  	return 0;
354  }
355  
do_tpm_init(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])356  int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
357  {
358  	struct udevice *dev;
359  	int rc;
360  
361  	if (argc != 1)
362  		return CMD_RET_USAGE;
363  	rc = get_tpm(&dev);
364  	if (rc)
365  		return rc;
366  
367  	return report_return_code(tpm_init(dev));
368  }
369  
do_tpm(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])370  int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
371  {
372  	cmd_tbl_t *tpm_commands, *cmd;
373  	struct tpm_chip_priv *priv;
374  	struct udevice *dev;
375  	unsigned int size;
376  	int ret;
377  
378  	if (argc < 2)
379  		return CMD_RET_USAGE;
380  
381  	ret = get_tpm(&dev);
382  	if (ret)
383  		return ret;
384  
385  	priv = dev_get_uclass_priv(dev);
386  
387  	/* Below getters return NULL if the desired stack is not built */
388  	switch (priv->version) {
389  	case TPM_V1:
390  		tpm_commands = get_tpm1_commands(&size);
391  		break;
392  	case TPM_V2:
393  		tpm_commands = get_tpm2_commands(&size);
394  		break;
395  	default:
396  		tpm_commands = NULL;
397  	}
398  
399  	if (!tpm_commands)
400  		return CMD_RET_USAGE;
401  
402  	cmd = find_cmd_tbl(argv[1], tpm_commands, size);
403  	if (!cmd)
404  		return CMD_RET_USAGE;
405  
406  	return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
407  }
408