uboot/cmd/tpm-common.c
<<
>>
Prefs
   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 <malloc.h>
  11#include <asm/unaligned.h>
  12#include <linux/string.h>
  13#include <tpm-common.h>
  14#include "tpm-user-utils.h"
  15
  16static 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 */
  24void 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 */
  51void *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)hextoul(byte, NULL);
  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 */
  86int 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 */
 102int 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 */
 114size_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 */
 145void *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 */
 169int 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 */
 207int 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
 237static 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
 256static 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
 277int 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
 299int do_tpm_device(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 300{
 301        unsigned long num;
 302        int rc;
 303
 304        if (argc == 2) {
 305                num = dectoul(argv[1], NULL);
 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
 317int do_tpm_info(struct cmd_tbl *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
 336int do_tpm_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 337{
 338        struct udevice *dev;
 339        int rc;
 340
 341        if (argc != 1)
 342                return CMD_RET_USAGE;
 343        rc = get_tpm(&dev);
 344        if (rc)
 345                return rc;
 346
 347        return report_return_code(tpm_init(dev));
 348}
 349
 350int do_tpm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 351{
 352        struct cmd_tbl *tpm_commands, *cmd;
 353        struct tpm_chip_priv *priv;
 354        struct udevice *dev;
 355        unsigned int size;
 356        int ret;
 357
 358        if (argc < 2)
 359                return CMD_RET_USAGE;
 360
 361        ret = get_tpm(&dev);
 362        if (ret)
 363                return ret;
 364
 365        priv = dev_get_uclass_priv(dev);
 366
 367        /* Below getters return NULL if the desired stack is not built */
 368        switch (priv->version) {
 369        case TPM_V1:
 370                tpm_commands = get_tpm1_commands(&size);
 371                break;
 372        case TPM_V2:
 373                tpm_commands = get_tpm2_commands(&size);
 374                break;
 375        default:
 376                tpm_commands = NULL;
 377        }
 378
 379        if (!tpm_commands)
 380                return CMD_RET_USAGE;
 381
 382        cmd = find_cmd_tbl(argv[1], tpm_commands, size);
 383        if (!cmd)
 384                return CMD_RET_USAGE;
 385
 386        return cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
 387}
 388