u-boot/lib/tpm-common.c
Miquel Raynal d677bfe2f7 tpm: disociate TPMv1.x specific and generic code
There are no changes in this commit but a new organization of the code
as follow.

* cmd/ directory:
        > move existing code from cmd/tpm.c in cmd/tpm-common.c
	> move specific code in cmd/tpm-v1.c
	> create a specific header file with generic definitions for
	  commands only called cmd/tpm-user-utils.h

* lib/ directory:
        > move existing code from lib/tpm.c in lib/tpm-common.c
	> move specific code in lib/tpm-v1.c
	> create a specific header file with generic definitions for
	  the library itself called lib/tpm-utils.h

* include/ directory:
        > move existing code from include/tpm.h in include/tpm-common.h
	> move specific code in include/tpm-v1.h

Code designated as 'common' is compiled if TPM are used. Code designated
as 'specific' is compiled only if the right specification has been
selected.

All files include tpm-common.h.
Files in cmd/ include tpm-user-utils.h.
Files in lib/ include tpm-utils.h.
Depending on the specification, files may include either (not both)
tpm-v1.h or tpm-v2.h.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
[trini: Fix a few more cases of tpm.h -> tpm-v1.h, some Kconfig logic]
Signed-off-by: Tom Rini <trini@konsulko.com>
2018-05-25 20:12:55 -04:00

188 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2013 The Chromium OS Authors.
* Coypright (c) 2013 Guntermann & Drunck GmbH
*/
#include <common.h>
#include <dm.h>
#include <asm/unaligned.h>
#include <tpm-common.h>
#include "tpm-utils.h"
int pack_byte_string(u8 *str, size_t size, const char *format, ...)
{
va_list args;
size_t offset = 0, length = 0;
u8 *data = NULL;
u32 value = 0;
va_start(args, format);
for (; *format; format++) {
switch (*format) {
case 'b':
offset = va_arg(args, size_t);
value = va_arg(args, int);
length = 1;
break;
case 'w':
offset = va_arg(args, size_t);
value = va_arg(args, int);
length = 2;
break;
case 'd':
offset = va_arg(args, size_t);
value = va_arg(args, u32);
length = 4;
break;
case 's':
offset = va_arg(args, size_t);
data = va_arg(args, u8 *);
length = va_arg(args, u32);
break;
default:
debug("Couldn't recognize format string\n");
va_end(args);
return -1;
}
if (offset + length > size) {
va_end(args);
return -1;
}
switch (*format) {
case 'b':
str[offset] = value;
break;
case 'w':
put_unaligned_be16(value, str + offset);
break;
case 'd':
put_unaligned_be32(value, str + offset);
break;
case 's':
memcpy(str + offset, data, length);
break;
}
}
va_end(args);
return 0;
}
int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
{
va_list args;
size_t offset = 0, length = 0;
u8 *ptr8 = NULL;
u16 *ptr16 = NULL;
u32 *ptr32 = NULL;
va_start(args, format);
for (; *format; format++) {
switch (*format) {
case 'b':
offset = va_arg(args, size_t);
ptr8 = va_arg(args, u8 *);
length = 1;
break;
case 'w':
offset = va_arg(args, size_t);
ptr16 = va_arg(args, u16 *);
length = 2;
break;
case 'd':
offset = va_arg(args, size_t);
ptr32 = va_arg(args, u32 *);
length = 4;
break;
case 's':
offset = va_arg(args, size_t);
ptr8 = va_arg(args, u8 *);
length = va_arg(args, u32);
break;
default:
va_end(args);
debug("Couldn't recognize format string\n");
return -1;
}
if (offset + length > size) {
va_end(args);
return -1;
}
switch (*format) {
case 'b':
*ptr8 = str[offset];
break;
case 'w':
*ptr16 = get_unaligned_be16(str + offset);
break;
case 'd':
*ptr32 = get_unaligned_be32(str + offset);
break;
case 's':
memcpy(ptr8, str + offset, length);
break;
}
}
va_end(args);
return 0;
}
u32 tpm_command_size(const void *command)
{
const size_t command_size_offset = 2;
return get_unaligned_be32(command + command_size_offset);
}
u32 tpm_return_code(const void *response)
{
const size_t return_code_offset = 6;
return get_unaligned_be32(response + return_code_offset);
}
u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr)
{
struct udevice *dev;
int err, ret;
u8 response_buffer[COMMAND_BUFFER_SIZE];
size_t response_length;
if (response) {
response_length = *size_ptr;
} else {
response = response_buffer;
response_length = sizeof(response_buffer);
}
ret = uclass_first_device_err(UCLASS_TPM, &dev);
if (ret)
return ret;
err = tpm_xfer(dev, command, tpm_command_size(command),
response, &response_length);
if (err < 0)
return TPM_LIB_ERROR;
if (size_ptr)
*size_ptr = response_length;
return tpm_return_code(response);
}
int tpm_init(void)
{
struct udevice *dev;
int err;
err = uclass_first_device_err(UCLASS_TPM, &dev);
if (err)
return err;
return tpm_open(dev);
}