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