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 15d677bfe2SMiquel Raynal int pack_byte_string(u8 *str, size_t size, const char *format, ...) 16d677bfe2SMiquel Raynal { 17d677bfe2SMiquel Raynal va_list args; 18d677bfe2SMiquel Raynal size_t offset = 0, length = 0; 19d677bfe2SMiquel Raynal u8 *data = NULL; 20d677bfe2SMiquel Raynal u32 value = 0; 21d677bfe2SMiquel Raynal 22d677bfe2SMiquel Raynal va_start(args, format); 23d677bfe2SMiquel Raynal for (; *format; format++) { 24d677bfe2SMiquel Raynal switch (*format) { 25d677bfe2SMiquel Raynal case 'b': 26d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 27d677bfe2SMiquel Raynal value = va_arg(args, int); 28d677bfe2SMiquel Raynal length = 1; 29d677bfe2SMiquel Raynal break; 30d677bfe2SMiquel Raynal case 'w': 31d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 32d677bfe2SMiquel Raynal value = va_arg(args, int); 33d677bfe2SMiquel Raynal length = 2; 34d677bfe2SMiquel Raynal break; 35d677bfe2SMiquel Raynal case 'd': 36d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 37d677bfe2SMiquel Raynal value = va_arg(args, u32); 38d677bfe2SMiquel Raynal length = 4; 39d677bfe2SMiquel Raynal break; 40d677bfe2SMiquel Raynal case 's': 41d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 42d677bfe2SMiquel Raynal data = va_arg(args, u8 *); 43d677bfe2SMiquel Raynal length = va_arg(args, u32); 44d677bfe2SMiquel Raynal break; 45d677bfe2SMiquel Raynal default: 46d677bfe2SMiquel Raynal debug("Couldn't recognize format string\n"); 47d677bfe2SMiquel Raynal va_end(args); 48d677bfe2SMiquel Raynal return -1; 49d677bfe2SMiquel Raynal } 50d677bfe2SMiquel Raynal 51d677bfe2SMiquel Raynal if (offset + length > size) { 52d677bfe2SMiquel Raynal va_end(args); 53d677bfe2SMiquel Raynal return -1; 54d677bfe2SMiquel Raynal } 55d677bfe2SMiquel Raynal 56d677bfe2SMiquel Raynal switch (*format) { 57d677bfe2SMiquel Raynal case 'b': 58d677bfe2SMiquel Raynal str[offset] = value; 59d677bfe2SMiquel Raynal break; 60d677bfe2SMiquel Raynal case 'w': 61d677bfe2SMiquel Raynal put_unaligned_be16(value, str + offset); 62d677bfe2SMiquel Raynal break; 63d677bfe2SMiquel Raynal case 'd': 64d677bfe2SMiquel Raynal put_unaligned_be32(value, str + offset); 65d677bfe2SMiquel Raynal break; 66d677bfe2SMiquel Raynal case 's': 67d677bfe2SMiquel Raynal memcpy(str + offset, data, length); 68d677bfe2SMiquel Raynal break; 69d677bfe2SMiquel Raynal } 70d677bfe2SMiquel Raynal } 71d677bfe2SMiquel Raynal va_end(args); 72d677bfe2SMiquel Raynal 73d677bfe2SMiquel Raynal return 0; 74d677bfe2SMiquel Raynal } 75d677bfe2SMiquel Raynal 76d677bfe2SMiquel Raynal int unpack_byte_string(const u8 *str, size_t size, const char *format, ...) 77d677bfe2SMiquel Raynal { 78d677bfe2SMiquel Raynal va_list args; 79d677bfe2SMiquel Raynal size_t offset = 0, length = 0; 80d677bfe2SMiquel Raynal u8 *ptr8 = NULL; 81d677bfe2SMiquel Raynal u16 *ptr16 = NULL; 82d677bfe2SMiquel Raynal u32 *ptr32 = NULL; 83d677bfe2SMiquel Raynal 84d677bfe2SMiquel Raynal va_start(args, format); 85d677bfe2SMiquel Raynal for (; *format; format++) { 86d677bfe2SMiquel Raynal switch (*format) { 87d677bfe2SMiquel Raynal case 'b': 88d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 89d677bfe2SMiquel Raynal ptr8 = va_arg(args, u8 *); 90d677bfe2SMiquel Raynal length = 1; 91d677bfe2SMiquel Raynal break; 92d677bfe2SMiquel Raynal case 'w': 93d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 94d677bfe2SMiquel Raynal ptr16 = va_arg(args, u16 *); 95d677bfe2SMiquel Raynal length = 2; 96d677bfe2SMiquel Raynal break; 97d677bfe2SMiquel Raynal case 'd': 98d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 99d677bfe2SMiquel Raynal ptr32 = va_arg(args, u32 *); 100d677bfe2SMiquel Raynal length = 4; 101d677bfe2SMiquel Raynal break; 102d677bfe2SMiquel Raynal case 's': 103d677bfe2SMiquel Raynal offset = va_arg(args, size_t); 104d677bfe2SMiquel Raynal ptr8 = va_arg(args, u8 *); 105d677bfe2SMiquel Raynal length = va_arg(args, u32); 106d677bfe2SMiquel Raynal break; 107d677bfe2SMiquel Raynal default: 108d677bfe2SMiquel Raynal va_end(args); 109d677bfe2SMiquel Raynal debug("Couldn't recognize format string\n"); 110d677bfe2SMiquel Raynal return -1; 111d677bfe2SMiquel Raynal } 112d677bfe2SMiquel Raynal 113d677bfe2SMiquel Raynal if (offset + length > size) { 114d677bfe2SMiquel Raynal va_end(args); 11534a5e8a2SSimon Glass log_err("Failed to read: size=%d, offset=%x, len=%x\n", 11634a5e8a2SSimon Glass size, offset, length); 117d677bfe2SMiquel Raynal return -1; 118d677bfe2SMiquel Raynal } 119d677bfe2SMiquel Raynal 120d677bfe2SMiquel Raynal switch (*format) { 121d677bfe2SMiquel Raynal case 'b': 122d677bfe2SMiquel Raynal *ptr8 = str[offset]; 123d677bfe2SMiquel Raynal break; 124d677bfe2SMiquel Raynal case 'w': 125d677bfe2SMiquel Raynal *ptr16 = get_unaligned_be16(str + offset); 126d677bfe2SMiquel Raynal break; 127d677bfe2SMiquel Raynal case 'd': 128d677bfe2SMiquel Raynal *ptr32 = get_unaligned_be32(str + offset); 129d677bfe2SMiquel Raynal break; 130d677bfe2SMiquel Raynal case 's': 131d677bfe2SMiquel Raynal memcpy(ptr8, str + offset, length); 132d677bfe2SMiquel Raynal break; 133d677bfe2SMiquel Raynal } 134d677bfe2SMiquel Raynal } 135d677bfe2SMiquel Raynal va_end(args); 136d677bfe2SMiquel Raynal 137d677bfe2SMiquel Raynal return 0; 138d677bfe2SMiquel Raynal } 139d677bfe2SMiquel Raynal 140d677bfe2SMiquel Raynal u32 tpm_command_size(const void *command) 141d677bfe2SMiquel Raynal { 142d677bfe2SMiquel Raynal const size_t command_size_offset = 2; 143d677bfe2SMiquel Raynal 144d677bfe2SMiquel Raynal return get_unaligned_be32(command + command_size_offset); 145d677bfe2SMiquel Raynal } 146d677bfe2SMiquel Raynal 147d677bfe2SMiquel Raynal u32 tpm_return_code(const void *response) 148d677bfe2SMiquel Raynal { 149d677bfe2SMiquel Raynal const size_t return_code_offset = 6; 150d677bfe2SMiquel Raynal 151d677bfe2SMiquel Raynal return get_unaligned_be32(response + return_code_offset); 152d677bfe2SMiquel Raynal } 153d677bfe2SMiquel Raynal 154*abdc7b8aSSimon Glass u32 tpm_sendrecv_command(struct udevice *dev, const void *command, 155*abdc7b8aSSimon Glass void *response, size_t *size_ptr) 156d677bfe2SMiquel Raynal { 157d677bfe2SMiquel Raynal int err, ret; 158d677bfe2SMiquel Raynal u8 response_buffer[COMMAND_BUFFER_SIZE]; 159d677bfe2SMiquel Raynal size_t response_length; 160aa643013SMiquel Raynal int i; 161d677bfe2SMiquel Raynal 162d677bfe2SMiquel Raynal if (response) { 163d677bfe2SMiquel Raynal response_length = *size_ptr; 164d677bfe2SMiquel Raynal } else { 165d677bfe2SMiquel Raynal response = response_buffer; 166d677bfe2SMiquel Raynal response_length = sizeof(response_buffer); 167d677bfe2SMiquel Raynal } 168d677bfe2SMiquel Raynal 169d677bfe2SMiquel Raynal err = tpm_xfer(dev, command, tpm_command_size(command), 170d677bfe2SMiquel Raynal response, &response_length); 171d677bfe2SMiquel Raynal 172d677bfe2SMiquel Raynal if (err < 0) 173bcdf6b9fSMiquel Raynal return err; 174bcdf6b9fSMiquel Raynal 175d677bfe2SMiquel Raynal if (size_ptr) 176d677bfe2SMiquel Raynal *size_ptr = response_length; 177d677bfe2SMiquel Raynal 178aa643013SMiquel Raynal ret = tpm_return_code(response); 179aa643013SMiquel Raynal 18034a5e8a2SSimon Glass log_debug("TPM response [ret:%d]: ", ret); 181aa643013SMiquel Raynal for (i = 0; i < response_length; i++) 18234a5e8a2SSimon Glass log_debug("%02x ", ((u8 *)response)[i]); 18334a5e8a2SSimon Glass log_debug("\n"); 184aa643013SMiquel Raynal 185aa643013SMiquel Raynal return ret; 186d677bfe2SMiquel Raynal } 187d677bfe2SMiquel Raynal 188*abdc7b8aSSimon Glass int tpm_init(struct udevice *dev) 189d677bfe2SMiquel Raynal { 190d677bfe2SMiquel Raynal return tpm_open(dev); 191d677bfe2SMiquel Raynal } 192