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