blob: a62862e94f91320a8a222c3cefea89f0722e0862 [file] [log] [blame]
Miquel Raynalf3b43502018-05-15 11:57:08 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 Bootlin
4 * Author: Miquel Raynal <miquel.raynal@bootlin.com>
5 */
6
Simon Glassed38aef2020-05-10 11:40:03 -06007#include <command.h>
Miquel Raynalf3b43502018-05-15 11:57:08 +02008#include <dm.h>
9#include <log.h>
Miquel Raynal14d72352018-05-15 11:57:15 +020010#include <mapmem.h>
Miquel Raynalf3b43502018-05-15 11:57:08 +020011#include <tpm-common.h>
12#include <tpm-v2.h>
13#include "tpm-user-utils.h"
14
Simon Glassed38aef2020-05-10 11:40:03 -060015static int do_tpm2_startup(struct cmd_tbl *cmdtp, int flag, int argc,
16 char *const argv[])
Miquel Raynal65a1a6c2018-05-15 11:57:12 +020017{
18 enum tpm2_startup_types mode;
Simon Glass8ceca1d2018-11-18 14:22:27 -070019 struct udevice *dev;
20 int ret;
Raymond Mao5187a642025-01-27 06:58:46 -080021 bool bon = true;
Miquel Raynal65a1a6c2018-05-15 11:57:12 +020022
Simon Glass8ceca1d2018-11-18 14:22:27 -070023 ret = get_tpm(&dev);
24 if (ret)
25 return ret;
Raymond Mao5187a642025-01-27 06:58:46 -080026
27 /* argv[2] is optional to perform a TPM2_CC_SHUTDOWN */
28 if (argc > 3 || (argc == 3 && strcasecmp("off", argv[2])))
Miquel Raynal65a1a6c2018-05-15 11:57:12 +020029 return CMD_RET_USAGE;
30
31 if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) {
32 mode = TPM2_SU_CLEAR;
33 } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) {
34 mode = TPM2_SU_STATE;
35 } else {
36 printf("Couldn't recognize mode string: %s\n", argv[1]);
37 return CMD_RET_FAILURE;
38 }
39
Raymond Mao5187a642025-01-27 06:58:46 -080040 if (argv[2])
41 bon = false;
42
43 return report_return_code(tpm2_startup(dev, bon, mode));
Miquel Raynal65a1a6c2018-05-15 11:57:12 +020044}
45
Simon Glassed38aef2020-05-10 11:40:03 -060046static int do_tpm2_self_test(struct cmd_tbl *cmdtp, int flag, int argc,
47 char *const argv[])
Miquel Raynal39c76082018-05-15 11:57:13 +020048{
49 enum tpm2_yes_no full_test;
Simon Glass8ceca1d2018-11-18 14:22:27 -070050 struct udevice *dev;
51 int ret;
Miquel Raynal39c76082018-05-15 11:57:13 +020052
Simon Glass8ceca1d2018-11-18 14:22:27 -070053 ret = get_tpm(&dev);
54 if (ret)
55 return ret;
Miquel Raynal39c76082018-05-15 11:57:13 +020056 if (argc != 2)
57 return CMD_RET_USAGE;
58
59 if (!strcasecmp("full", argv[1])) {
60 full_test = TPMI_YES;
61 } else if (!strcasecmp("continue", argv[1])) {
62 full_test = TPMI_NO;
63 } else {
64 printf("Couldn't recognize test mode: %s\n", argv[1]);
65 return CMD_RET_FAILURE;
66 }
67
Simon Glass8ceca1d2018-11-18 14:22:27 -070068 return report_return_code(tpm2_self_test(dev, full_test));
Miquel Raynal39c76082018-05-15 11:57:13 +020069}
70
Simon Glassed38aef2020-05-10 11:40:03 -060071static int do_tpm2_clear(struct cmd_tbl *cmdtp, int flag, int argc,
72 char *const argv[])
Miquel Raynal8df6f8d2018-05-15 11:57:14 +020073{
74 u32 handle = 0;
75 const char *pw = (argc < 3) ? NULL : argv[2];
76 const ssize_t pw_sz = pw ? strlen(pw) : 0;
Simon Glass8ceca1d2018-11-18 14:22:27 -070077 struct udevice *dev;
78 int ret;
79
80 ret = get_tpm(&dev);
81 if (ret)
82 return ret;
Miquel Raynal8df6f8d2018-05-15 11:57:14 +020083
84 if (argc < 2 || argc > 3)
85 return CMD_RET_USAGE;
86
87 if (pw_sz > TPM2_DIGEST_LEN)
88 return -EINVAL;
89
90 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
91 handle = TPM2_RH_LOCKOUT;
92 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
93 handle = TPM2_RH_PLATFORM;
94 else
95 return CMD_RET_USAGE;
96
Simon Glass8ceca1d2018-11-18 14:22:27 -070097 return report_return_code(tpm2_clear(dev, handle, pw, pw_sz));
Miquel Raynal8df6f8d2018-05-15 11:57:14 +020098}
99
Simon Glassed38aef2020-05-10 11:40:03 -0600100static int do_tpm2_pcr_extend(struct cmd_tbl *cmdtp, int flag, int argc,
101 char *const argv[])
Miquel Raynal14d72352018-05-15 11:57:15 +0200102{
103 struct udevice *dev;
104 struct tpm_chip_priv *priv;
105 u32 index = simple_strtoul(argv[1], NULL, 0);
106 void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
Tim Harveybbfa6082024-05-25 13:00:49 -0700107 int algo = TPM2_ALG_SHA256;
108 int algo_len;
Miquel Raynal14d72352018-05-15 11:57:15 +0200109 int ret;
110 u32 rc;
111
Tim Harveybbfa6082024-05-25 13:00:49 -0700112 if (argc < 3 || argc > 4)
Miquel Raynal14d72352018-05-15 11:57:15 +0200113 return CMD_RET_USAGE;
Tim Harveybbfa6082024-05-25 13:00:49 -0700114 if (argc == 4) {
115 algo = tpm2_name_to_algorithm(argv[3]);
116 if (algo < 0)
117 return CMD_RET_FAILURE;
118 }
119 algo_len = tpm2_algorithm_to_len(algo);
Miquel Raynal14d72352018-05-15 11:57:15 +0200120
Simon Glass8ceca1d2018-11-18 14:22:27 -0700121 ret = get_tpm(&dev);
Miquel Raynal14d72352018-05-15 11:57:15 +0200122 if (ret)
123 return ret;
124
125 priv = dev_get_uclass_priv(dev);
126 if (!priv)
127 return -EINVAL;
128
129 if (index >= priv->pcr_count)
130 return -EINVAL;
131
Tim Harveybbfa6082024-05-25 13:00:49 -0700132 rc = tpm2_pcr_extend(dev, index, algo, digest, algo_len);
133 if (!rc) {
134 printf("PCR #%u extended with %d byte %s digest\n", index,
135 algo_len, tpm2_algorithm_name(algo));
136 print_byte_string(digest, algo_len);
137 }
Miquel Raynal14d72352018-05-15 11:57:15 +0200138
139 unmap_sysmem(digest);
140
141 return report_return_code(rc);
142}
143
Simon Glassed38aef2020-05-10 11:40:03 -0600144static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
145 char *const argv[])
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200146{
Tim Harveybbfa6082024-05-25 13:00:49 -0700147 enum tpm2_algorithms algo = TPM2_ALG_SHA256;
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200148 struct udevice *dev;
149 struct tpm_chip_priv *priv;
150 u32 index, rc;
Tim Harveybbfa6082024-05-25 13:00:49 -0700151 int algo_len;
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200152 unsigned int updates;
153 void *data;
154 int ret;
155
Tim Harveybbfa6082024-05-25 13:00:49 -0700156 if (argc < 3 || argc > 4)
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200157 return CMD_RET_USAGE;
Tim Harveybbfa6082024-05-25 13:00:49 -0700158 if (argc == 4) {
159 algo = tpm2_name_to_algorithm(argv[3]);
160 if (algo < 0)
161 return CMD_RET_FAILURE;
162 }
163 algo_len = tpm2_algorithm_to_len(algo);
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200164
Simon Glass8ceca1d2018-11-18 14:22:27 -0700165 ret = get_tpm(&dev);
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200166 if (ret)
167 return ret;
168
169 priv = dev_get_uclass_priv(dev);
170 if (!priv)
171 return -EINVAL;
172
173 index = simple_strtoul(argv[1], NULL, 0);
174 if (index >= priv->pcr_count)
175 return -EINVAL;
176
177 data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0);
178
Tim Harveybbfa6082024-05-25 13:00:49 -0700179 rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, algo,
180 data, algo_len, &updates);
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200181 if (!rc) {
Tim Harveybbfa6082024-05-25 13:00:49 -0700182 printf("PCR #%u %s %d byte content (%u known updates):\n", index,
183 tpm2_algorithm_name(algo), algo_len, updates);
184 print_byte_string(data, algo_len);
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200185 }
186
187 unmap_sysmem(data);
188
189 return report_return_code(rc);
190}
191
Simon Glassed38aef2020-05-10 11:40:03 -0600192static int do_tpm_get_capability(struct cmd_tbl *cmdtp, int flag, int argc,
193 char *const argv[])
Miquel Raynal2e52c062018-05-15 11:57:17 +0200194{
195 u32 capability, property, rc;
196 u8 *data;
197 size_t count;
198 int i, j;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700199 struct udevice *dev;
200 int ret;
201
202 ret = get_tpm(&dev);
203 if (ret)
204 return ret;
Miquel Raynal2e52c062018-05-15 11:57:17 +0200205
206 if (argc != 5)
207 return CMD_RET_USAGE;
208
209 capability = simple_strtoul(argv[1], NULL, 0);
210 property = simple_strtoul(argv[2], NULL, 0);
211 data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
212 count = simple_strtoul(argv[4], NULL, 0);
213
Simon Glass8ceca1d2018-11-18 14:22:27 -0700214 rc = tpm2_get_capability(dev, capability, property, data, count);
Miquel Raynal2e52c062018-05-15 11:57:17 +0200215 if (rc)
216 goto unmap_data;
217
218 printf("Capabilities read from TPM:\n");
219 for (i = 0; i < count; i++) {
220 printf("Property 0x");
221 for (j = 0; j < 4; j++)
Ilias Apalodimasa0789152020-11-05 23:58:43 +0200222 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
Miquel Raynal2e52c062018-05-15 11:57:17 +0200223 printf(": 0x");
224 for (j = 4; j < 8; j++)
Ilias Apalodimasa0789152020-11-05 23:58:43 +0200225 printf("%02x", data[(i * 8) + j + sizeof(u32)]);
Miquel Raynal2e52c062018-05-15 11:57:17 +0200226 printf("\n");
227 }
228
229unmap_data:
230 unmap_sysmem(data);
231
232 return report_return_code(rc);
233}
234
Raymond Maof69f2d72025-01-27 06:58:47 -0800235static u32 select_mask(u32 mask, enum tpm2_algorithms algo, bool select)
236{
237 size_t i;
238
239 for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
240 if (hash_algo_list[i].hash_alg != algo)
241 continue;
242
243 if (select)
244 mask |= hash_algo_list[i].hash_mask;
245 else
246 mask &= ~hash_algo_list[i].hash_mask;
247
248 break;
249 }
250
251 return mask;
252}
253
254static bool
255is_algo_in_pcrs(enum tpm2_algorithms algo, struct tpml_pcr_selection *pcrs)
256{
257 size_t i;
258
259 for (i = 0; i < pcrs->count; i++) {
260 if (algo == pcrs->selection[i].hash)
261 return true;
262 }
263
264 return false;
265}
266
267static int do_tpm2_pcrallocate(struct cmd_tbl *cmdtp, int flag, int argc,
268 char *const argv[])
269{
270 struct udevice *dev;
271 int ret;
272 enum tpm2_algorithms algo;
273 const char *pw = (argc < 4) ? NULL : argv[3];
274 const ssize_t pw_sz = pw ? strlen(pw) : 0;
275 static struct tpml_pcr_selection pcr = { 0 };
276 u32 pcr_len = 0;
277 bool bon = false;
278 static u32 mask;
279 int i;
280
281 /* argv[1]: algorithm (bank), argv[2]: on/off */
282 if (argc < 3 || argc > 4)
283 return CMD_RET_USAGE;
284
285 if (!strcasecmp("on", argv[2]))
286 bon = true;
287 else if (strcasecmp("off", argv[2]))
288 return CMD_RET_USAGE;
289
290 algo = tpm2_name_to_algorithm(argv[1]);
291 if (algo == -EINVAL)
292 return CMD_RET_USAGE;
293
294 ret = get_tpm(&dev);
295 if (ret)
296 return ret;
297
298 if (!pcr.count) {
299 /*
300 * Get current active algorithms (banks), PCRs and mask via the
301 * first call
302 */
303 ret = tpm2_get_pcr_info(dev, &pcr);
304 if (ret)
305 return ret;
306
307 for (i = 0; i < pcr.count; i++) {
308 struct tpms_pcr_selection *sel = &pcr.selection[i];
309 const char *name;
310
311 if (!tpm2_is_active_bank(sel))
312 continue;
313
314 mask = select_mask(mask, sel->hash, true);
315 name = tpm2_algorithm_name(sel->hash);
316 if (name)
317 printf("Active bank[%d]: %s\n", i, name);
318 }
319 }
320
321 if (!is_algo_in_pcrs(algo, &pcr)) {
322 printf("%s is not supported by the tpm device\n", argv[1]);
323 return CMD_RET_USAGE;
324 }
325
326 mask = select_mask(mask, algo, bon);
327 ret = tpm2_pcr_config_algo(dev, mask, &pcr, &pcr_len);
328 if (ret)
329 return ret;
330
331 return report_return_code(tpm2_send_pcr_allocate(dev, pw, pw_sz, &pcr,
332 pcr_len));
333}
334
Simon Glassed38aef2020-05-10 11:40:03 -0600335static int do_tpm_dam_reset(struct cmd_tbl *cmdtp, int flag, int argc,
Miquel Raynal228e9902018-05-15 11:57:18 +0200336 char *const argv[])
337{
338 const char *pw = (argc < 2) ? NULL : argv[1];
339 const ssize_t pw_sz = pw ? strlen(pw) : 0;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700340 struct udevice *dev;
341 int ret;
342
343 ret = get_tpm(&dev);
344 if (ret)
345 return ret;
Miquel Raynal228e9902018-05-15 11:57:18 +0200346
347 if (argc > 2)
348 return CMD_RET_USAGE;
349
350 if (pw_sz > TPM2_DIGEST_LEN)
351 return -EINVAL;
352
Simon Glass8ceca1d2018-11-18 14:22:27 -0700353 return report_return_code(tpm2_dam_reset(dev, pw, pw_sz));
Miquel Raynal228e9902018-05-15 11:57:18 +0200354}
355
Simon Glassed38aef2020-05-10 11:40:03 -0600356static int do_tpm_dam_parameters(struct cmd_tbl *cmdtp, int flag, int argc,
Miquel Raynal228e9902018-05-15 11:57:18 +0200357 char *const argv[])
358{
359 const char *pw = (argc < 5) ? NULL : argv[4];
360 const ssize_t pw_sz = pw ? strlen(pw) : 0;
361 /*
362 * No Dictionary Attack Mitigation (DAM) means:
363 * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0
364 */
365 unsigned long int max_tries;
366 unsigned long int recovery_time;
367 unsigned long int lockout_recovery;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700368 struct udevice *dev;
369 int ret;
370
371 ret = get_tpm(&dev);
372 if (ret)
373 return ret;
Miquel Raynal228e9902018-05-15 11:57:18 +0200374
375 if (argc < 4 || argc > 5)
376 return CMD_RET_USAGE;
377
378 if (pw_sz > TPM2_DIGEST_LEN)
379 return -EINVAL;
380
381 if (strict_strtoul(argv[1], 0, &max_tries))
382 return CMD_RET_USAGE;
383
384 if (strict_strtoul(argv[2], 0, &recovery_time))
385 return CMD_RET_USAGE;
386
387 if (strict_strtoul(argv[3], 0, &lockout_recovery))
388 return CMD_RET_USAGE;
389
390 log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n");
391 log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries);
392 log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time);
393 log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery);
394
Simon Glass8ceca1d2018-11-18 14:22:27 -0700395 return report_return_code(tpm2_dam_parameters(dev, pw, pw_sz, max_tries,
Miquel Raynal228e9902018-05-15 11:57:18 +0200396 recovery_time,
397 lockout_recovery));
398}
399
Simon Glassed38aef2020-05-10 11:40:03 -0600400static int do_tpm_change_auth(struct cmd_tbl *cmdtp, int flag, int argc,
Miquel Raynal05d7be32018-05-15 11:57:19 +0200401 char *const argv[])
402{
403 u32 handle;
404 const char *newpw = argv[2];
405 const char *oldpw = (argc == 3) ? NULL : argv[3];
406 const ssize_t newpw_sz = strlen(newpw);
407 const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700408 struct udevice *dev;
409 int ret;
410
411 ret = get_tpm(&dev);
412 if (ret)
413 return ret;
Miquel Raynal05d7be32018-05-15 11:57:19 +0200414
415 if (argc < 3 || argc > 4)
416 return CMD_RET_USAGE;
417
418 if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN)
419 return -EINVAL;
420
421 if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1]))
422 handle = TPM2_RH_LOCKOUT;
423 else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1]))
424 handle = TPM2_RH_ENDORSEMENT;
425 else if (!strcasecmp("TPM2_RH_OWNER", argv[1]))
426 handle = TPM2_RH_OWNER;
427 else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1]))
428 handle = TPM2_RH_PLATFORM;
429 else
430 return CMD_RET_USAGE;
431
Simon Glass8ceca1d2018-11-18 14:22:27 -0700432 return report_return_code(tpm2_change_auth(dev, handle, newpw, newpw_sz,
Miquel Raynal05d7be32018-05-15 11:57:19 +0200433 oldpw, oldpw_sz));
434}
435
Simon Glassed38aef2020-05-10 11:40:03 -0600436static int do_tpm_pcr_setauthpolicy(struct cmd_tbl *cmdtp, int flag, int argc,
437 char *const argv[])
Miquel Raynal0b864f62018-05-15 11:57:20 +0200438{
439 u32 index = simple_strtoul(argv[1], NULL, 0);
440 char *key = argv[2];
441 const char *pw = (argc < 4) ? NULL : argv[3];
442 const ssize_t pw_sz = pw ? strlen(pw) : 0;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700443 struct udevice *dev;
444 int ret;
445
446 ret = get_tpm(&dev);
447 if (ret)
448 return ret;
Miquel Raynal0b864f62018-05-15 11:57:20 +0200449
450 if (strlen(key) != TPM2_DIGEST_LEN)
451 return -EINVAL;
452
453 if (argc < 3 || argc > 4)
454 return CMD_RET_USAGE;
455
Simon Glass8ceca1d2018-11-18 14:22:27 -0700456 return report_return_code(tpm2_pcr_setauthpolicy(dev, pw, pw_sz, index,
Miquel Raynal0b864f62018-05-15 11:57:20 +0200457 key));
458}
459
Simon Glassed38aef2020-05-10 11:40:03 -0600460static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
461 int argc, char *const argv[])
Miquel Raynal0b864f62018-05-15 11:57:20 +0200462{
463 u32 index = simple_strtoul(argv[1], NULL, 0);
464 char *key = argv[2];
465 const ssize_t key_sz = strlen(key);
466 const char *pw = (argc < 4) ? NULL : argv[3];
467 const ssize_t pw_sz = pw ? strlen(pw) : 0;
Simon Glass8ceca1d2018-11-18 14:22:27 -0700468 struct udevice *dev;
469 int ret;
470
471 ret = get_tpm(&dev);
472 if (ret)
473 return ret;
Miquel Raynal0b864f62018-05-15 11:57:20 +0200474
475 if (strlen(key) != TPM2_DIGEST_LEN)
476 return -EINVAL;
477
478 if (argc < 3 || argc > 4)
479 return CMD_RET_USAGE;
480
Simon Glass8ceca1d2018-11-18 14:22:27 -0700481 return report_return_code(tpm2_pcr_setauthvalue(dev, pw, pw_sz, index,
Miquel Raynal0b864f62018-05-15 11:57:20 +0200482 key, key_sz));
483}
484
Simon Glassed38aef2020-05-10 11:40:03 -0600485static struct cmd_tbl tpm2_commands[] = {
Philippe Reynescbe97392020-01-09 18:45:46 +0100486 U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
Miquel Raynalf3b43502018-05-15 11:57:08 +0200487 U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
Simon Glass11a075c2022-08-30 21:05:36 -0600488 U_BOOT_CMD_MKENT(state, 0, 1, do_tpm_report_state, "", ""),
Miquel Raynalf3b43502018-05-15 11:57:08 +0200489 U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""),
Miquel Raynal65a1a6c2018-05-15 11:57:12 +0200490 U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""),
Miquel Raynal39c76082018-05-15 11:57:13 +0200491 U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""),
Miquel Raynal8df6f8d2018-05-15 11:57:14 +0200492 U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""),
Miquel Raynal14d72352018-05-15 11:57:15 +0200493 U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""),
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200494 U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""),
Miquel Raynal2e52c062018-05-15 11:57:17 +0200495 U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""),
Miquel Raynal228e9902018-05-15 11:57:18 +0200496 U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""),
497 U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""),
Miquel Raynal05d7be32018-05-15 11:57:19 +0200498 U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""),
Ilias Apalodimas3be89262023-06-07 12:18:10 +0300499 U_BOOT_CMD_MKENT(autostart, 0, 1, do_tpm_autostart, "", ""),
Miquel Raynal0b864f62018-05-15 11:57:20 +0200500 U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1,
501 do_tpm_pcr_setauthpolicy, "", ""),
502 U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
503 do_tpm_pcr_setauthvalue, "", ""),
Raymond Maof69f2d72025-01-27 06:58:47 -0800504 U_BOOT_CMD_MKENT(pcr_allocate, 0, 1, do_tpm2_pcrallocate, "", ""),
Miquel Raynalf3b43502018-05-15 11:57:08 +0200505};
506
Simon Glassed38aef2020-05-10 11:40:03 -0600507struct cmd_tbl *get_tpm2_commands(unsigned int *size)
Miquel Raynalf3b43502018-05-15 11:57:08 +0200508{
509 *size = ARRAY_SIZE(tpm2_commands);
510
511 return tpm2_commands;
512}
513
Miquel Raynal79920d12018-07-19 22:35:09 +0200514U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
Miquel Raynalf3b43502018-05-15 11:57:08 +0200515"<command> [<arguments>]\n"
516"\n"
Philippe Reynescbe97392020-01-09 18:45:46 +0100517"device [num device]\n"
518" Show all devices or set the specified device\n"
Miquel Raynalf3b43502018-05-15 11:57:08 +0200519"info\n"
520" Show information about the TPM.\n"
Simon Glass11a075c2022-08-30 21:05:36 -0600521"state\n"
522" Show internal state from the TPM (if available)\n"
Ilias Apalodimas3be89262023-06-07 12:18:10 +0300523"autostart\n"
524" Initalize the tpm, perform a Startup(clear) and run a full selftest\n"
525" sequence\n"
Miquel Raynalf3b43502018-05-15 11:57:08 +0200526"init\n"
527" Initialize the software stack. Always the first command to issue.\n"
Ilias Apalodimas3be89262023-06-07 12:18:10 +0300528" 'tpm startup' is the only acceptable command after a 'tpm init' has been\n"
529" issued\n"
Raymond Mao5187a642025-01-27 06:58:46 -0800530"startup <mode> [<op>]\n"
Miquel Raynal65a1a6c2018-05-15 11:57:12 +0200531" Issue a TPM2_Startup command.\n"
532" <mode> is one of:\n"
533" * TPM2_SU_CLEAR (reset state)\n"
534" * TPM2_SU_STATE (preserved state)\n"
Raymond Mao5187a642025-01-27 06:58:46 -0800535" <op>:\n"
536" * off - To shutdown the TPM\n"
Miquel Raynal39c76082018-05-15 11:57:13 +0200537"self_test <type>\n"
538" Test the TPM capabilities.\n"
539" <type> is one of:\n"
540" * full (perform all tests)\n"
541" * continue (only check untested tests)\n"
Miquel Raynal8df6f8d2018-05-15 11:57:14 +0200542"clear <hierarchy>\n"
543" Issue a TPM2_Clear command.\n"
544" <hierarchy> is one of:\n"
545" * TPM2_RH_LOCKOUT\n"
546" * TPM2_RH_PLATFORM\n"
Tim Harveybbfa6082024-05-25 13:00:49 -0700547"pcr_extend <pcr> <digest_addr> [<digest_algo>]\n"
548" Extend PCR #<pcr> with digest at <digest_addr> with digest_algo.\n"
Miquel Raynal14d72352018-05-15 11:57:15 +0200549" <pcr>: index of the PCR\n"
Tim Harveybbfa6082024-05-25 13:00:49 -0700550" <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n"
551"pcr_read <pcr> <digest_addr> [<digest_algo>]\n"
552" Read PCR #<pcr> to memory address <digest_addr> with <digest_algo>.\n"
Miquel Raynal4c1a5852018-05-15 11:57:16 +0200553" <pcr>: index of the PCR\n"
Tim Harveybbfa6082024-05-25 13:00:49 -0700554" <digest_addr>: address of digest of digest_algo type (defaults to SHA256)\n"
Miquel Raynal2e52c062018-05-15 11:57:17 +0200555"get_capability <capability> <property> <addr> <count>\n"
556" Read and display <count> entries indexed by <capability>/<property>.\n"
557" Values are 4 bytes long and are written at <addr>.\n"
558" <capability>: capability\n"
559" <property>: property\n"
560" <addr>: address to store <count> entries of 4 bytes\n"
561" <count>: number of entries to retrieve\n"
Miquel Raynal05d7be32018-05-15 11:57:19 +0200562"dam_reset [<password>]\n"
563" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n"
564" <password>: optional password\n"
565"dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n"
566" If the TPM is not in a LOCKOUT state, set the DAM parameters\n"
567" <maxTries>: maximum number of failures before lockout,\n"
568" 0 means always locking\n"
569" <recoveryTime>: time before decrement of the error counter,\n"
570" 0 means no lockout\n"
571" <lockoutRecovery>: time of a lockout (before the next try),\n"
572" 0 means a reboot is needed\n"
573" <password>: optional password of the LOCKOUT hierarchy\n"
574"change_auth <hierarchy> <new_pw> [<old_pw>]\n"
575" <hierarchy>: the hierarchy\n"
576" <new_pw>: new password for <hierarchy>\n"
577" <old_pw>: optional previous password of <hierarchy>\n"
Miquel Raynal0b864f62018-05-15 11:57:20 +0200578"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n"
579" Change the <key> to access PCR #<pcr>.\n"
580" hierarchy and may be empty.\n"
581" /!\\WARNING: untested function, use at your own risks !\n"
582" <pcr>: index of the PCR\n"
583" <key>: secret to protect the access of PCR #<pcr>\n"
584" <password>: optional password of the PLATFORM hierarchy\n"
Raymond Maof69f2d72025-01-27 06:58:47 -0800585"pcr_allocate <algorithm> <on/off> [<password>]\n"
586" Issue a TPM2_PCR_Allocate Command to reconfig PCR bank algorithm.\n"
587" <algorithm> is one of:\n"
588" * sha1\n"
589" * sha256\n"
590" * sha384\n"
591" * sha512\n"
592" <on|off> is one of:\n"
593" * on - Select all available PCRs associated with the specified\n"
594" algorithm (bank)\n"
595" * off - Clear all available PCRs associated with the specified\n"
596" algorithm (bank)\n"
597" <password>: optional password\n"
Miquel Raynalf3b43502018-05-15 11:57:08 +0200598);