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