uboot/lib/tpm-common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2013 The Chromium OS Authors.
   4 * Coypright (c) 2013 Guntermann & Drunck GmbH
   5 */
   6
   7#define LOG_CATEGORY UCLASS_TPM
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <asm/unaligned.h>
  12#include <tpm-common.h>
  13#include "tpm-utils.h"
  14
  15enum tpm_version tpm_get_version(struct udevice *dev)
  16{
  17        struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
  18
  19        return priv->version;
  20}
  21
  22int pack_byte_string(u8 *str, size_t size, const char *format, ...)
  23{
  24        va_list args;
  25        size_t offset = 0, length = 0;
  26        u8 *data = NULL;
  27        u32 value = 0;
  28
  29        va_start(args, format);
  30        for (; *format; format++) {
  31                switch (*format) {
  32                case 'b':
  33                        offset = va_arg(args, size_t);
  34                        value = va_arg(args, int);
  35                        length = 1;
  36                        break;
  37                case 'w':
  38                        offset = va_arg(args, size_t);
  39                        value = va_arg(args, int);
  40                        length = 2;
  41                        break;
  42                case 'd':
  43                        offset = va_arg(args, size_t);
  44                        value = va_arg(args, u32);
  45                        length = 4;
  46                        break;
  47                case 's':
  48                        offset = va_arg(args, size_t);
  49                        data = va_arg(args, u8 *);
  50                        length = va_arg(args, u32);
  51                        break;
  52                default:
  53                        debug("Couldn't recognize format string\n");
  54                        va_end(args);
  55                        return -1;
  56                }
  57
  58                if (offset + length > size) {
  59                        va_end(args);
  60                        return -1;
  61                }
  62
  63                switch (*format) {
  64                case 'b':
  65                        str[offset] = value;
  66                        break;
  67                case 'w':
  68                        put_unaligned_be16(value, str + offset);
  69                        break;
  70                case 'd':
  71                        put_unaligned_be32(value, str + offset);
  72                        break;
  73                case 's':
  74                        memcpy(str + offset, data, length);
  75                        break;
  76                }
  77        }
  78        va_end(args);
  79
  80        return 0;
  81}
  82
  83int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
  84{
  85        va_list args;
  86        size_t offset = 0, length = 0;
  87        u8 *ptr8 = NULL;
  88        u16 *ptr16 = NULL;
  89        u32 *ptr32 = NULL;
  90
  91        va_start(args, format);
  92        for (; *format; format++) {
  93                switch (*format) {
  94                case 'b':
  95                        offset = va_arg(args, size_t);
  96                        ptr8 = va_arg(args, u8 *);
  97                        length = 1;
  98                        break;
  99                case 'w':
 100                        offset = va_arg(args, size_t);
 101                        ptr16 = va_arg(args, u16 *);
 102                        length = 2;
 103                        break;
 104                case 'd':
 105                        offset = va_arg(args, size_t);
 106                        ptr32 = va_arg(args, u32 *);
 107                        length = 4;
 108                        break;
 109                case 's':
 110                        offset = va_arg(args, size_t);
 111                        ptr8 = va_arg(args, u8 *);
 112                        length = va_arg(args, u32);
 113                        break;
 114                default:
 115                        va_end(args);
 116                        debug("Couldn't recognize format string\n");
 117                        return -1;
 118                }
 119
 120                if (offset + length > size) {
 121                        va_end(args);
 122                        log_err("Failed to read: size=%zd, offset=%zx, len=%zx\n",
 123                                size, offset, length);
 124                        return -1;
 125                }
 126
 127                switch (*format) {
 128                case 'b':
 129                        *ptr8 = str[offset];
 130                        break;
 131                case 'w':
 132                        *ptr16 = get_unaligned_be16(str + offset);
 133                        break;
 134                case 'd':
 135                        *ptr32 = get_unaligned_be32(str + offset);
 136                        break;
 137                case 's':
 138                        memcpy(ptr8, str + offset, length);
 139                        break;
 140                }
 141        }
 142        va_end(args);
 143
 144        return 0;
 145}
 146
 147u32 tpm_command_size(const void *command)
 148{
 149        const size_t command_size_offset = 2;
 150
 151        return get_unaligned_be32(command + command_size_offset);
 152}
 153
 154u32 tpm_return_code(const void *response)
 155{
 156        const size_t return_code_offset = 6;
 157
 158        return get_unaligned_be32(response + return_code_offset);
 159}
 160
 161u32 tpm_sendrecv_command(struct udevice *dev, const void *command,
 162                         void *response, size_t *size_ptr)
 163{
 164        int err, ret;
 165        u8 response_buffer[COMMAND_BUFFER_SIZE];
 166        size_t response_length;
 167        int i;
 168
 169        if (response) {
 170                response_length = *size_ptr;
 171        } else {
 172                response = response_buffer;
 173                response_length = sizeof(response_buffer);
 174        }
 175
 176        err = tpm_xfer(dev, command, tpm_command_size(command),
 177                       response, &response_length);
 178
 179        if (err < 0)
 180                return err;
 181
 182        if (size_ptr)
 183                *size_ptr = response_length;
 184
 185        ret = tpm_return_code(response);
 186
 187        log_debug("TPM response [ret:%d]: ", ret);
 188        for (i = 0; i < response_length; i++)
 189                log_debug("%02x ", ((u8 *)response)[i]);
 190        log_debug("\n");
 191
 192        return ret;
 193}
 194
 195int tpm_init(struct udevice *dev)
 196{
 197        return tpm_open(dev);
 198}
 199