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