uboot/cmd/tpm.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 The Chromium OS Authors.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <command.h>
   9#include <dm.h>
  10#include <malloc.h>
  11#include <tpm.h>
  12#include <asm/unaligned.h>
  13#include <linux/string.h>
  14
  15/* Useful constants */
  16enum {
  17        DIGEST_LENGTH           = 20,
  18        /* max lengths, valid for RSA keys <= 2048 bits */
  19        TPM_PUBKEY_MAX_LENGTH   = 288,
  20};
  21
  22/**
  23 * Print a byte string in hexdecimal format, 16-bytes per line.
  24 *
  25 * @param data          byte string to be printed
  26 * @param count         number of bytes to be printed
  27 */
  28static void print_byte_string(uint8_t *data, size_t count)
  29{
  30        int i, print_newline = 0;
  31
  32        for (i = 0; i < count; i++) {
  33                printf(" %02x", data[i]);
  34                print_newline = (i % 16 == 15);
  35                if (print_newline)
  36                        putc('\n');
  37        }
  38        /* Avoid duplicated newline at the end */
  39        if (!print_newline)
  40                putc('\n');
  41}
  42
  43/**
  44 * Convert a text string of hexdecimal values into a byte string.
  45 *
  46 * @param bytes         text string of hexdecimal values with no space
  47 *                      between them
  48 * @param data          output buffer for byte string.  The caller has to make
  49 *                      sure it is large enough for storing the output.  If
  50 *                      NULL is passed, a large enough buffer will be allocated,
  51 *                      and the caller must free it.
  52 * @param count_ptr     output variable for the length of byte string
  53 * @return pointer to output buffer
  54 */
  55static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr)
  56{
  57        char byte[3];
  58        size_t count, length;
  59        int i;
  60
  61        if (!bytes)
  62                return NULL;
  63        length = strlen(bytes);
  64        count = length / 2;
  65
  66        if (!data)
  67                data = malloc(count);
  68        if (!data)
  69                return NULL;
  70
  71        byte[2] = '\0';
  72        for (i = 0; i < length; i += 2) {
  73                byte[0] = bytes[i];
  74                byte[1] = bytes[i + 1];
  75                data[i / 2] = (uint8_t)simple_strtoul(byte, NULL, 16);
  76        }
  77
  78        if (count_ptr)
  79                *count_ptr = count;
  80
  81        return data;
  82}
  83
  84/**
  85 * report_return_code() - Report any error and return failure or success
  86 *
  87 * @param return_code   TPM command return code
  88 * @return value of enum command_ret_t
  89 */
  90static int report_return_code(int return_code)
  91{
  92        if (return_code) {
  93                printf("Error: %d\n", return_code);
  94                return CMD_RET_FAILURE;
  95        } else {
  96                return CMD_RET_SUCCESS;
  97        }
  98}
  99
 100/**
 101 * Return number of values defined by a type string.
 102 *
 103 * @param type_str      type string
 104 * @return number of values of type string
 105 */
 106static int type_string_get_num_values(const char *type_str)
 107{
 108        return strlen(type_str);
 109}
 110
 111/**
 112 * Return total size of values defined by a type string.
 113 *
 114 * @param type_str      type string
 115 * @return total size of values of type string, or 0 if type string
 116 *  contains illegal type character.
 117 */
 118static size_t type_string_get_space_size(const char *type_str)
 119{
 120        size_t size;
 121
 122        for (size = 0; *type_str; type_str++) {
 123                switch (*type_str) {
 124                case 'b':
 125                        size += 1;
 126                        break;
 127                case 'w':
 128                        size += 2;
 129                        break;
 130                case 'd':
 131                        size += 4;
 132                        break;
 133                default:
 134                        return 0;
 135                }
 136        }
 137
 138        return size;
 139}
 140
 141/**
 142 * Allocate a buffer large enough to hold values defined by a type
 143 * string.  The caller has to free the buffer.
 144 *
 145 * @param type_str      type string
 146 * @param count         pointer for storing size of buffer
 147 * @return pointer to buffer or NULL on error
 148 */
 149static void *type_string_alloc(const char *type_str, uint32_t *count)
 150{
 151        void *data;
 152        size_t size;
 153
 154        size = type_string_get_space_size(type_str);
 155        if (!size)
 156                return NULL;
 157        data = malloc(size);
 158        if (data)
 159                *count = size;
 160
 161        return data;
 162}
 163
 164/**
 165 * Pack values defined by a type string into a buffer.  The buffer must have
 166 * large enough space.
 167 *
 168 * @param type_str      type string
 169 * @param values        text strings of values to be packed
 170 * @param data          output buffer of values
 171 * @return 0 on success, non-0 on error
 172 */
 173static int type_string_pack(const char *type_str, char * const values[],
 174                uint8_t *data)
 175{
 176        size_t offset;
 177        uint32_t value;
 178
 179        for (offset = 0; *type_str; type_str++, values++) {
 180                value = simple_strtoul(values[0], NULL, 0);
 181                switch (*type_str) {
 182                case 'b':
 183                        data[offset] = value;
 184                        offset += 1;
 185                        break;
 186                case 'w':
 187                        put_unaligned_be16(value, data + offset);
 188                        offset += 2;
 189                        break;
 190                case 'd':
 191                        put_unaligned_be32(value, data + offset);
 192                        offset += 4;
 193                        break;
 194                default:
 195                        return -1;
 196                }
 197        }
 198
 199        return 0;
 200}
 201
 202/**
 203 * Read values defined by a type string from a buffer, and write these values
 204 * to environment variables.
 205 *
 206 * @param type_str      type string
 207 * @param data          input buffer of values
 208 * @param vars          names of environment variables
 209 * @return 0 on success, non-0 on error
 210 */
 211static int type_string_write_vars(const char *type_str, uint8_t *data,
 212                char * const vars[])
 213{
 214        size_t offset;
 215        uint32_t value;
 216
 217        for (offset = 0; *type_str; type_str++, vars++) {
 218                switch (*type_str) {
 219                case 'b':
 220                        value = data[offset];
 221                        offset += 1;
 222                        break;
 223                case 'w':
 224                        value = get_unaligned_be16(data + offset);
 225                        offset += 2;
 226                        break;
 227                case 'd':
 228                        value = get_unaligned_be32(data + offset);
 229                        offset += 4;
 230                        break;
 231                default:
 232                        return -1;
 233                }
 234                if (setenv_ulong(*vars, value))
 235                        return -1;
 236        }
 237
 238        return 0;
 239}
 240
 241static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag,
 242                int argc, char * const argv[])
 243{
 244        enum tpm_startup_type mode;
 245
 246        if (argc != 2)
 247                return CMD_RET_USAGE;
 248        if (!strcasecmp("TPM_ST_CLEAR", argv[1])) {
 249                mode = TPM_ST_CLEAR;
 250        } else if (!strcasecmp("TPM_ST_STATE", argv[1])) {
 251                mode = TPM_ST_STATE;
 252        } else if (!strcasecmp("TPM_ST_DEACTIVATED", argv[1])) {
 253                mode = TPM_ST_DEACTIVATED;
 254        } else {
 255                printf("Couldn't recognize mode string: %s\n", argv[1]);
 256                return CMD_RET_FAILURE;
 257        }
 258
 259        return report_return_code(tpm_startup(mode));
 260}
 261
 262static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag,
 263                int argc, char * const argv[])
 264{
 265        uint32_t index, perm, size;
 266
 267        if (argc != 4)
 268                return CMD_RET_USAGE;
 269        index = simple_strtoul(argv[1], NULL, 0);
 270        perm = simple_strtoul(argv[2], NULL, 0);
 271        size = simple_strtoul(argv[3], NULL, 0);
 272
 273        return report_return_code(tpm_nv_define_space(index, perm, size));
 274}
 275
 276static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag,
 277                int argc, char * const argv[])
 278{
 279        uint32_t index, count, rc;
 280        void *data;
 281
 282        if (argc != 4)
 283                return CMD_RET_USAGE;
 284        index = simple_strtoul(argv[1], NULL, 0);
 285        data = (void *)simple_strtoul(argv[2], NULL, 0);
 286        count = simple_strtoul(argv[3], NULL, 0);
 287
 288        rc = tpm_nv_read_value(index, data, count);
 289        if (!rc) {
 290                puts("area content:\n");
 291                print_byte_string(data, count);
 292        }
 293
 294        return report_return_code(rc);
 295}
 296
 297static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag,
 298                int argc, char * const argv[])
 299{
 300        uint32_t index, rc;
 301        size_t count;
 302        void *data;
 303
 304        if (argc != 3)
 305                return CMD_RET_USAGE;
 306        index = simple_strtoul(argv[1], NULL, 0);
 307        data = parse_byte_string(argv[2], NULL, &count);
 308        if (!data) {
 309                printf("Couldn't parse byte string %s\n", argv[2]);
 310                return CMD_RET_FAILURE;
 311        }
 312
 313        rc = tpm_nv_write_value(index, data, count);
 314        free(data);
 315
 316        return report_return_code(rc);
 317}
 318
 319static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag,
 320                int argc, char * const argv[])
 321{
 322        uint32_t index, rc;
 323        uint8_t in_digest[20], out_digest[20];
 324
 325        if (argc != 3)
 326                return CMD_RET_USAGE;
 327        index = simple_strtoul(argv[1], NULL, 0);
 328        if (!parse_byte_string(argv[2], in_digest, NULL)) {
 329                printf("Couldn't parse byte string %s\n", argv[2]);
 330                return CMD_RET_FAILURE;
 331        }
 332
 333        rc = tpm_extend(index, in_digest, out_digest);
 334        if (!rc) {
 335                puts("PCR value after execution of the command:\n");
 336                print_byte_string(out_digest, sizeof(out_digest));
 337        }
 338
 339        return report_return_code(rc);
 340}
 341
 342static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag,
 343                int argc, char * const argv[])
 344{
 345        uint32_t index, count, rc;
 346        void *data;
 347
 348        if (argc != 4)
 349                return CMD_RET_USAGE;
 350        index = simple_strtoul(argv[1], NULL, 0);
 351        data = (void *)simple_strtoul(argv[2], NULL, 0);
 352        count = simple_strtoul(argv[3], NULL, 0);
 353
 354        rc = tpm_pcr_read(index, data, count);
 355        if (!rc) {
 356                puts("Named PCR content:\n");
 357                print_byte_string(data, count);
 358        }
 359
 360        return report_return_code(rc);
 361}
 362
 363static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag,
 364                int argc, char * const argv[])
 365{
 366        uint16_t presence;
 367
 368        if (argc != 2)
 369                return CMD_RET_USAGE;
 370        presence = (uint16_t)simple_strtoul(argv[1], NULL, 0);
 371
 372        return report_return_code(tpm_tsc_physical_presence(presence));
 373}
 374
 375static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag,
 376                int argc, char * const argv[])
 377{
 378        uint32_t count, rc;
 379        void *data;
 380
 381        if (argc != 3)
 382                return CMD_RET_USAGE;
 383        data = (void *)simple_strtoul(argv[1], NULL, 0);
 384        count = simple_strtoul(argv[2], NULL, 0);
 385
 386        rc = tpm_read_pubek(data, count);
 387        if (!rc) {
 388                puts("pubek value:\n");
 389                print_byte_string(data, count);
 390        }
 391
 392        return report_return_code(rc);
 393}
 394
 395static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag,
 396                int argc, char * const argv[])
 397{
 398        uint8_t state;
 399
 400        if (argc != 2)
 401                return CMD_RET_USAGE;
 402        state = (uint8_t)simple_strtoul(argv[1], NULL, 0);
 403
 404        return report_return_code(tpm_physical_set_deactivated(state));
 405}
 406
 407static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag,
 408                int argc, char * const argv[])
 409{
 410        uint32_t cap_area, sub_cap, rc;
 411        void *cap;
 412        size_t count;
 413
 414        if (argc != 5)
 415                return CMD_RET_USAGE;
 416        cap_area = simple_strtoul(argv[1], NULL, 0);
 417        sub_cap = simple_strtoul(argv[2], NULL, 0);
 418        cap = (void *)simple_strtoul(argv[3], NULL, 0);
 419        count = simple_strtoul(argv[4], NULL, 0);
 420
 421        rc = tpm_get_capability(cap_area, sub_cap, cap, count);
 422        if (!rc) {
 423                puts("capability information:\n");
 424                print_byte_string(cap, count);
 425        }
 426
 427        return report_return_code(rc);
 428}
 429
 430#define TPM_COMMAND_NO_ARG(cmd)                         \
 431static int do_##cmd(cmd_tbl_t *cmdtp, int flag,         \
 432                int argc, char * const argv[])          \
 433{                                                       \
 434        if (argc != 1)                                  \
 435                return CMD_RET_USAGE;                   \
 436        return report_return_code(cmd());               \
 437}
 438
 439TPM_COMMAND_NO_ARG(tpm_init)
 440TPM_COMMAND_NO_ARG(tpm_self_test_full)
 441TPM_COMMAND_NO_ARG(tpm_continue_self_test)
 442TPM_COMMAND_NO_ARG(tpm_force_clear)
 443TPM_COMMAND_NO_ARG(tpm_physical_enable)
 444TPM_COMMAND_NO_ARG(tpm_physical_disable)
 445
 446static int get_tpm(struct udevice **devp)
 447{
 448        int rc;
 449
 450        rc = uclass_first_device_err(UCLASS_TPM, devp);
 451        if (rc) {
 452                printf("Could not find TPM (ret=%d)\n", rc);
 453                return CMD_RET_FAILURE;
 454        }
 455
 456        return 0;
 457}
 458
 459static int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc,
 460                       char *const argv[])
 461{
 462        struct udevice *dev;
 463        char buf[80];
 464        int rc;
 465
 466        rc = get_tpm(&dev);
 467        if (rc)
 468                return rc;
 469        rc = tpm_get_desc(dev, buf, sizeof(buf));
 470        if (rc < 0) {
 471                printf("Couldn't get TPM info (%d)\n", rc);
 472                return CMD_RET_FAILURE;
 473        }
 474        printf("%s\n", buf);
 475
 476        return 0;
 477}
 478
 479static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag,
 480                int argc, char * const argv[])
 481{
 482        struct udevice *dev;
 483        void *command;
 484        uint8_t response[1024];
 485        size_t count, response_length = sizeof(response);
 486        uint32_t rc;
 487
 488        command = parse_byte_string(argv[1], NULL, &count);
 489        if (!command) {
 490                printf("Couldn't parse byte string %s\n", argv[1]);
 491                return CMD_RET_FAILURE;
 492        }
 493
 494        rc = get_tpm(&dev);
 495        if (rc)
 496                return rc;
 497
 498        rc = tpm_xfer(dev, command, count, response, &response_length);
 499        free(command);
 500        if (!rc) {
 501                puts("tpm response:\n");
 502                print_byte_string(response, response_length);
 503        }
 504
 505        return report_return_code(rc);
 506}
 507
 508static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag,
 509                int argc, char * const argv[])
 510{
 511        uint32_t index, perm, size;
 512
 513        if (argc != 4)
 514                return CMD_RET_USAGE;
 515        size = type_string_get_space_size(argv[1]);
 516        if (!size) {
 517                printf("Couldn't parse arguments\n");
 518                return CMD_RET_USAGE;
 519        }
 520        index = simple_strtoul(argv[2], NULL, 0);
 521        perm = simple_strtoul(argv[3], NULL, 0);
 522
 523        return report_return_code(tpm_nv_define_space(index, perm, size));
 524}
 525
 526static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag,
 527                int argc, char * const argv[])
 528{
 529        uint32_t index, count, err;
 530        void *data;
 531
 532        if (argc < 3)
 533                return CMD_RET_USAGE;
 534        if (argc != 3 + type_string_get_num_values(argv[1]))
 535                return CMD_RET_USAGE;
 536        index = simple_strtoul(argv[2], NULL, 0);
 537        data = type_string_alloc(argv[1], &count);
 538        if (!data) {
 539                printf("Couldn't parse arguments\n");
 540                return CMD_RET_USAGE;
 541        }
 542
 543        err = tpm_nv_read_value(index, data, count);
 544        if (!err) {
 545                if (type_string_write_vars(argv[1], data, argv + 3)) {
 546                        printf("Couldn't write to variables\n");
 547                        err = ~0;
 548                }
 549        }
 550        free(data);
 551
 552        return report_return_code(err);
 553}
 554
 555static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag,
 556                int argc, char * const argv[])
 557{
 558        uint32_t index, count, err;
 559        void *data;
 560
 561        if (argc < 3)
 562                return CMD_RET_USAGE;
 563        if (argc != 3 + type_string_get_num_values(argv[1]))
 564                return CMD_RET_USAGE;
 565        index = simple_strtoul(argv[2], NULL, 0);
 566        data = type_string_alloc(argv[1], &count);
 567        if (!data) {
 568                printf("Couldn't parse arguments\n");
 569                return CMD_RET_USAGE;
 570        }
 571        if (type_string_pack(argv[1], argv + 3, data)) {
 572                printf("Couldn't parse arguments\n");
 573                free(data);
 574                return CMD_RET_USAGE;
 575        }
 576
 577        err = tpm_nv_write_value(index, data, count);
 578        free(data);
 579
 580        return report_return_code(err);
 581}
 582
 583#ifdef CONFIG_TPM_AUTH_SESSIONS
 584
 585static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag,
 586                int argc, char * const argv[])
 587{
 588        uint32_t auth_handle, err;
 589
 590        err = tpm_oiap(&auth_handle);
 591
 592        return report_return_code(err);
 593}
 594
 595static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag,
 596                int argc, char * const argv[])
 597{
 598        uint32_t parent_handle, key_len, key_handle, err;
 599        uint8_t usage_auth[DIGEST_LENGTH];
 600        void *key;
 601
 602        if (argc < 5)
 603                return CMD_RET_USAGE;
 604
 605        parent_handle = simple_strtoul(argv[1], NULL, 0);
 606        key = (void *)simple_strtoul(argv[2], NULL, 0);
 607        key_len = simple_strtoul(argv[3], NULL, 0);
 608        if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
 609                return CMD_RET_FAILURE;
 610        parse_byte_string(argv[4], usage_auth, NULL);
 611
 612        err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
 613                        &key_handle);
 614        if (!err)
 615                printf("Key handle is 0x%x\n", key_handle);
 616
 617        return report_return_code(err);
 618}
 619
 620static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag,
 621                int argc, char * const argv[])
 622{
 623        uint32_t key_handle, err;
 624        uint8_t usage_auth[DIGEST_LENGTH];
 625        uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH];
 626        size_t pub_key_len = sizeof(pub_key_buffer);
 627
 628        if (argc < 3)
 629                return CMD_RET_USAGE;
 630
 631        key_handle = simple_strtoul(argv[1], NULL, 0);
 632        if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
 633                return CMD_RET_FAILURE;
 634        parse_byte_string(argv[2], usage_auth, NULL);
 635
 636        err = tpm_get_pub_key_oiap(key_handle, usage_auth,
 637                        pub_key_buffer, &pub_key_len);
 638        if (!err) {
 639                printf("dump of received pub key structure:\n");
 640                print_byte_string(pub_key_buffer, pub_key_len);
 641        }
 642        return report_return_code(err);
 643}
 644
 645TPM_COMMAND_NO_ARG(tpm_end_oiap)
 646
 647#endif /* CONFIG_TPM_AUTH_SESSIONS */
 648
 649#define MAKE_TPM_CMD_ENTRY(cmd) \
 650        U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
 651
 652static cmd_tbl_t tpm_commands[] = {
 653        U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
 654        U_BOOT_CMD_MKENT(init, 0, 1,
 655                        do_tpm_init, "", ""),
 656        U_BOOT_CMD_MKENT(startup, 0, 1,
 657                        do_tpm_startup, "", ""),
 658        U_BOOT_CMD_MKENT(self_test_full, 0, 1,
 659                        do_tpm_self_test_full, "", ""),
 660        U_BOOT_CMD_MKENT(continue_self_test, 0, 1,
 661                        do_tpm_continue_self_test, "", ""),
 662        U_BOOT_CMD_MKENT(force_clear, 0, 1,
 663                        do_tpm_force_clear, "", ""),
 664        U_BOOT_CMD_MKENT(physical_enable, 0, 1,
 665                        do_tpm_physical_enable, "", ""),
 666        U_BOOT_CMD_MKENT(physical_disable, 0, 1,
 667                        do_tpm_physical_disable, "", ""),
 668        U_BOOT_CMD_MKENT(nv_define_space, 0, 1,
 669                        do_tpm_nv_define_space, "", ""),
 670        U_BOOT_CMD_MKENT(nv_read_value, 0, 1,
 671                        do_tpm_nv_read_value, "", ""),
 672        U_BOOT_CMD_MKENT(nv_write_value, 0, 1,
 673                        do_tpm_nv_write_value, "", ""),
 674        U_BOOT_CMD_MKENT(extend, 0, 1,
 675                        do_tpm_extend, "", ""),
 676        U_BOOT_CMD_MKENT(pcr_read, 0, 1,
 677                        do_tpm_pcr_read, "", ""),
 678        U_BOOT_CMD_MKENT(tsc_physical_presence, 0, 1,
 679                        do_tpm_tsc_physical_presence, "", ""),
 680        U_BOOT_CMD_MKENT(read_pubek, 0, 1,
 681                        do_tpm_read_pubek, "", ""),
 682        U_BOOT_CMD_MKENT(physical_set_deactivated, 0, 1,
 683                        do_tpm_physical_set_deactivated, "", ""),
 684        U_BOOT_CMD_MKENT(get_capability, 0, 1,
 685                        do_tpm_get_capability, "", ""),
 686        U_BOOT_CMD_MKENT(raw_transfer, 0, 1,
 687                        do_tpm_raw_transfer, "", ""),
 688        U_BOOT_CMD_MKENT(nv_define, 0, 1,
 689                        do_tpm_nv_define, "", ""),
 690        U_BOOT_CMD_MKENT(nv_read, 0, 1,
 691                        do_tpm_nv_read, "", ""),
 692        U_BOOT_CMD_MKENT(nv_write, 0, 1,
 693                        do_tpm_nv_write, "", ""),
 694#ifdef CONFIG_TPM_AUTH_SESSIONS
 695        U_BOOT_CMD_MKENT(oiap, 0, 1,
 696                         do_tpm_oiap, "", ""),
 697        U_BOOT_CMD_MKENT(end_oiap, 0, 1,
 698                         do_tpm_end_oiap, "", ""),
 699        U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
 700                         do_tpm_load_key2_oiap, "", ""),
 701        U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
 702                         do_tpm_get_pub_key_oiap, "", ""),
 703#endif /* CONFIG_TPM_AUTH_SESSIONS */
 704};
 705
 706static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 707{
 708        cmd_tbl_t *tpm_cmd;
 709
 710        if (argc < 2)
 711                return CMD_RET_USAGE;
 712        tpm_cmd = find_cmd_tbl(argv[1], tpm_commands, ARRAY_SIZE(tpm_commands));
 713        if (!tpm_cmd)
 714                return CMD_RET_USAGE;
 715
 716        return tpm_cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
 717}
 718
 719U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
 720"Issue a TPM command",
 721"cmd args...\n"
 722"    - Issue TPM command <cmd> with arguments <args...>.\n"
 723"Admin Startup and State Commands:\n"
 724"  info - Show information about the TPM\n"
 725"  init\n"
 726"    - Put TPM into a state where it waits for 'startup' command.\n"
 727"  startup mode\n"
 728"    - Issue TPM_Starup command.  <mode> is one of TPM_ST_CLEAR,\n"
 729"      TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
 730"Admin Testing Commands:\n"
 731"  self_test_full\n"
 732"    - Test all of the TPM capabilities.\n"
 733"  continue_self_test\n"
 734"    - Inform TPM that it should complete the self-test.\n"
 735"Admin Opt-in Commands:\n"
 736"  physical_enable\n"
 737"    - Set the PERMANENT disable flag to FALSE using physical presence as\n"
 738"      authorization.\n"
 739"  physical_disable\n"
 740"    - Set the PERMANENT disable flag to TRUE using physical presence as\n"
 741"      authorization.\n"
 742"  physical_set_deactivated 0|1\n"
 743"    - Set deactivated flag.\n"
 744"Admin Ownership Commands:\n"
 745"  force_clear\n"
 746"    - Issue TPM_ForceClear command.\n"
 747"  tsc_physical_presence flags\n"
 748"    - Set TPM device's Physical Presence flags to <flags>.\n"
 749"The Capability Commands:\n"
 750"  get_capability cap_area sub_cap addr count\n"
 751"    - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
 752"      <sub_cap> to memory address <addr>.\n"
 753#ifdef CONFIG_TPM_AUTH_SESSIONS
 754"Storage functions\n"
 755"  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
 756"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
 757"      into TPM using the parent key <parent_handle> with authorization\n"
 758"      <usage_auth> (20 bytes hex string).\n"
 759"  get_pub_key_oiap key_handle usage_auth\n"
 760"    - get the public key portion of a loaded key <key_handle> using\n"
 761"      authorization <usage auth> (20 bytes hex string)\n"
 762#endif /* CONFIG_TPM_AUTH_SESSIONS */
 763"Endorsement Key Handling Commands:\n"
 764"  read_pubek addr count\n"
 765"    - Read <count> bytes of the public endorsement key to memory\n"
 766"      address <addr>\n"
 767"Integrity Collection and Reporting Commands:\n"
 768"  extend index digest_hex_string\n"
 769"    - Add a new measurement to a PCR.  Update PCR <index> with the 20-bytes\n"
 770"      <digest_hex_string>\n"
 771"  pcr_read index addr count\n"
 772"    - Read <count> bytes from PCR <index> to memory address <addr>.\n"
 773#ifdef CONFIG_TPM_AUTH_SESSIONS
 774"Authorization Sessions\n"
 775"  oiap\n"
 776"    - setup an OIAP session\n"
 777"  end_oiap\n"
 778"    - terminates an active OIAP session\n"
 779#endif /* CONFIG_TPM_AUTH_SESSIONS */
 780"Non-volatile Storage Commands:\n"
 781"  nv_define_space index permission size\n"
 782"    - Establish a space at index <index> with <permission> of <size> bytes.\n"
 783"  nv_read_value index addr count\n"
 784"    - Read <count> bytes from space <index> to memory address <addr>.\n"
 785"  nv_write_value index addr count\n"
 786"    - Write <count> bytes from memory address <addr> to space <index>.\n"
 787"Miscellaneous helper functions:\n"
 788"  raw_transfer byte_string\n"
 789"    - Send a byte string <byte_string> to TPM and print the response.\n"
 790" Non-volatile storage helper functions:\n"
 791"    These helper functions treat a non-volatile space as a non-padded\n"
 792"    sequence of integer values.  These integer values are defined by a type\n"
 793"    string, which is a text string of 'bwd' characters: 'b' means a 8-bit\n"
 794"    value, 'w' 16-bit value, 'd' 32-bit value.  All helper functions take\n"
 795"    a type string as their first argument.\n"
 796"  nv_define type_string index perm\n"
 797"    - Define a space <index> with permission <perm>.\n"
 798"  nv_read types_string index vars...\n"
 799"    - Read from space <index> to environment variables <vars...>.\n"
 800"  nv_write types_string index values...\n"
 801"    - Write to space <index> from values <values...>.\n"
 802);
 803