Merge tpm 2017/12/22 v1

-----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJaPWUZAAoJEHWtZYAqC0IRe2oH/1tRMtwtoO2rvd7JBdIgl56J
 q+PTTOc/vI+YU9Yr7U0/oRnuX+QRswtLsWII8PKjj0bDc5eRm8NcT0dA7OmJ1KcV
 wgfIr8PsaO3Rz73ZV7AJ2epJuFJ8jJvfRiJ4nCdDXMGblmQHVurYPaUAf4OJkWTA
 a8He8zImjW5Qw51CMfU1Dq9MZfGaHc/i1HNo7kusEn9pEAzjQ8dSqJPYo/TIsLyK
 5dXSSWDQCRSXbd84Ft2idMFmIbZYVAihNuclc7oQ6wqMYH7oin0KV3h2QSGwFdFb
 FPlGEsoZ5Yk805ZCblkfqSGPI3Y9R2ZkgAgEP4TD+6dJOB8T35c2XdQo8YMI3G8=
 =NbNT
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2017-12-22-1' into staging

Merge tpm 2017/12/22 v1

# gpg: Signature made Fri 22 Dec 2017 20:03:37 GMT
# gpg:                using RSA key 0x75AD65802A0B4211
# gpg: Good signature from "Stefan Berger <stefanb@linux.vnet.ibm.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B818 B9CA DF90 89C2 D5CE  C66B 75AD 6580 2A0B 4211

* remotes/stefanberger/tags/pull-tpm-2017-12-22-1:
  acpi: Update TPM2 ACPI table to more recent specs
  tpm: Implement tpm_sized_buffer_reset
  tpm_tis: merge r/w_offset into rw_offset
  tpm_tis: move r/w_offsets to TPMState
  tpm_tis: merge read and write buffer into single buffer
  tpm_tis: move buffers from localities into common location
  tpm_tis: remove TPMSizeBuffer usage
  tpm_tis: limit size of buffer from backend
  tpm_tis: convert uint32_t to size_t
  tpm_emulator: Add a caching layer for the TPM Established flag

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-01-08 10:16:40 +00:00
commit b1e513ae33
6 changed files with 92 additions and 95 deletions

View File

@ -2274,16 +2274,25 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
}
static void
build_tpm2(GArray *table_data, BIOSLinker *linker)
build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
{
Acpi20TPM2 *tpm2_ptr;
tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
Acpi20TPM2 *tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr);
unsigned log_addr_size = sizeof(tpm2_ptr->log_area_start_address);
unsigned log_addr_offset =
(char *)&tpm2_ptr->log_area_start_address - table_data->data;
tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT);
if (TPM_IS_TIS(tpm_find())) {
tpm2_ptr->control_area_address = cpu_to_le64(0);
tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
tpm2_ptr->log_area_minimum_length =
cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
/* log area start address to be filled by Guest linker */
bios_linker_loader_add_pointer(linker,
ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
ACPI_BUILD_TPMLOG_FILE, 0);
} else {
g_warn_if_reached();
}
@ -2695,7 +2704,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
if (misc.tpm_version == TPM_VERSION_2_0) {
acpi_add_table(table_offsets, tables_blob);
build_tpm2(tables_blob, tables->linker);
build_tpm2(tables_blob, tables->linker, tables->tcpalog);
}
}
if (pcms->numa_nodes) {

View File

@ -72,6 +72,9 @@ typedef struct TPMEmulator {
Error *migration_blocker;
QemuMutex mutex;
unsigned int established_flag:1;
unsigned int established_flag_cached:1;
} TPMEmulator;
@ -349,16 +352,22 @@ static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
ptm_est est;
DPRINTF("%s", __func__);
if (tpm_emu->established_flag_cached) {
return tpm_emu->established_flag;
}
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_GET_TPMESTABLISHED, &est,
0, sizeof(est)) < 0) {
error_report("tpm-emulator: Could not get the TPM established flag: %s",
strerror(errno));
return false;
}
DPRINTF("established flag: %0x", est.u.resp.bit);
DPRINTF("got established flag: %0x", est.u.resp.bit);
return (est.u.resp.bit != 0);
tpm_emu->established_flag_cached = 1;
tpm_emu->established_flag = (est.u.resp.bit != 0);
return tpm_emu->established_flag;
}
static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
@ -389,6 +398,8 @@ static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
return -1;
}
tpm_emu->established_flag_cached = 0;
return 0;
}

View File

@ -48,11 +48,6 @@ typedef enum {
TPM_TIS_STATE_RECEPTION,
} TPMTISState;
typedef struct TPMSizedBuffer {
uint32_t size;
uint8_t *buffer;
} TPMSizedBuffer;
/* locality data -- all fields are persisted */
typedef struct TPMLocality {
TPMTISState state;
@ -61,19 +56,14 @@ typedef struct TPMLocality {
uint32_t iface_id;
uint32_t inte;
uint32_t ints;
uint16_t w_offset;
uint16_t r_offset;
TPMSizedBuffer w_buffer;
TPMSizedBuffer r_buffer;
} TPMLocality;
typedef struct TPMState {
ISADevice busdev;
MemoryRegion mmio;
uint32_t offset;
uint8_t buf[TPM_TIS_BUFFER_MAX];
unsigned char buffer[TPM_TIS_BUFFER_MAX];
uint16_t rw_offset;
uint8_t active_locty;
uint8_t aborting_locty;
@ -215,23 +205,19 @@ static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
}
static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb)
{
return tpm_cmd_get_size(sb->buffer);
}
static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
static void tpm_tis_show_buffer(const unsigned char *buffer,
size_t buffer_size, const char *string)
{
#ifdef DEBUG_TIS
uint32_t len, i;
len = tpm_tis_get_size_from_buffer(sb);
len = MIN(tpm_cmd_get_size(buffer), buffer_size);
DPRINTF("tpm_tis: %s length = %d\n", string, len);
for (i = 0; i < len; i++) {
if (i && !(i % 16)) {
DPRINTF("\n");
}
DPRINTF("%.2X ", sb->buffer[i]);
DPRINTF("%.2X ", buffer[i]);
}
DPRINTF("\n");
#endif
@ -261,22 +247,21 @@ static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
*/
static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
{
TPMLocality *locty_data = &s->loc[locty];
tpm_tis_show_buffer(&s->loc[locty].w_buffer, "tpm_tis: To TPM");
tpm_tis_show_buffer(s->buffer, s->be_buffer_size,
"tpm_tis: To TPM");
/*
* w_offset serves as length indicator for length of data;
* rw_offset serves as length indicator for length of data;
* it's reset when the response comes back
*/
s->loc[locty].state = TPM_TIS_STATE_EXECUTION;
s->cmd = (TPMBackendCmd) {
.locty = locty,
.in = locty_data->w_buffer.buffer,
.in_len = locty_data->w_offset,
.out = locty_data->r_buffer.buffer,
.out_len = locty_data->r_buffer.size
.in = s->buffer,
.in_len = s->rw_offset,
.out = s->buffer,
.out_len = s->be_buffer_size,
};
tpm_backend_deliver_request(s->be_driver, &s->cmd);
@ -356,8 +341,7 @@ static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
/* abort -- this function switches the locality */
static void tpm_tis_abort(TPMState *s, uint8_t locty)
{
s->loc[locty].r_offset = 0;
s->loc[locty].w_offset = 0;
s->rw_offset = 0;
DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", s->next_locty);
@ -424,10 +408,10 @@ static void tpm_tis_request_completed(TPMIf *ti)
tpm_tis_sts_set(&s->loc[locty],
TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
s->loc[locty].r_offset = 0;
s->loc[locty].w_offset = 0;
s->rw_offset = 0;
tpm_tis_show_buffer(&s->loc[locty].r_buffer, "tpm_tis: From TPM");
tpm_tis_show_buffer(s->buffer, s->be_buffer_size,
"tpm_tis: From TPM");
if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
tpm_tis_abort(s, locty);
@ -446,16 +430,17 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
uint16_t len;
if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
len = tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer);
len = MIN(tpm_cmd_get_size(&s->buffer),
s->be_buffer_size);
ret = s->loc[locty].r_buffer.buffer[s->loc[locty].r_offset++];
if (s->loc[locty].r_offset >= len) {
ret = s->buffer[s->rw_offset++];
if (s->rw_offset >= len) {
/* got last byte */
tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID);
tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
}
DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x [%d]\n",
ret, s->loc[locty].r_offset - 1);
ret, s->rw_offset - 1);
}
return ret;
@ -490,27 +475,15 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr)
(int)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
}
DPRINTF("tpm_tis: read offset : %d\n"
DPRINTF("tpm_tis: r/w offset : %d\n"
"tpm_tis: result buffer : ",
s->loc[locty].r_offset);
s->rw_offset);
for (idx = 0;
idx < tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer);
idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);
idx++) {
DPRINTF("%c%02x%s",
s->loc[locty].r_offset == idx ? '>' : ' ',
s->loc[locty].r_buffer.buffer[idx],
((idx & 0xf) == 0xf) ? "\ntpm_tis: " : "");
}
DPRINTF("\n"
"tpm_tis: write offset : %d\n"
"tpm_tis: request buffer: ",
s->loc[locty].w_offset);
for (idx = 0;
idx < tpm_tis_get_size_from_buffer(&s->loc[locty].w_buffer);
idx++) {
DPRINTF("%c%02x%s",
s->loc[locty].w_offset == idx ? '>' : ' ',
s->loc[locty].w_buffer.buffer[idx],
s->rw_offset == idx ? '>' : ' ',
s->buffer[idx],
((idx & 0xf) == 0xf) ? "\ntpm_tis: " : "");
}
DPRINTF("\n");
@ -572,11 +545,11 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
if (s->active_locty == locty) {
if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
val = TPM_TIS_BURST_COUNT(
tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer)
- s->loc[locty].r_offset) | s->loc[locty].sts;
MIN(tpm_cmd_get_size(&s->buffer),
s->be_buffer_size)
- s->rw_offset) | s->loc[locty].sts;
} else {
avail = s->loc[locty].w_buffer.size
- s->loc[locty].w_offset;
avail = s->be_buffer_size - s->rw_offset;
/*
* byte-sized reads should not return 0x00 for 0x100
* available bytes.
@ -840,8 +813,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
switch (s->loc[locty].state) {
case TPM_TIS_STATE_READY:
s->loc[locty].w_offset = 0;
s->loc[locty].r_offset = 0;
s->rw_offset = 0;
break;
case TPM_TIS_STATE_IDLE:
@ -859,8 +831,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
break;
case TPM_TIS_STATE_COMPLETION:
s->loc[locty].w_offset = 0;
s->loc[locty].r_offset = 0;
s->rw_offset = 0;
/* shortcut to ready state with C/R set */
s->loc[locty].state = TPM_TIS_STATE_READY;
if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
@ -886,7 +857,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
} else if (val == TPM_TIS_STS_RESPONSE_RETRY) {
switch (s->loc[locty].state) {
case TPM_TIS_STATE_COMPLETION:
s->loc[locty].r_offset = 0;
s->rw_offset = 0;
tpm_tis_sts_set(&s->loc[locty],
TPM_TIS_STS_VALID|
TPM_TIS_STS_DATA_AVAILABLE);
@ -924,9 +895,9 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
}
while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) {
if (s->loc[locty].w_offset < s->loc[locty].w_buffer.size) {
s->loc[locty].w_buffer.
buffer[s->loc[locty].w_offset++] = (uint8_t)val;
if (s->rw_offset < s->be_buffer_size) {
s->buffer[s->rw_offset++] =
(uint8_t)val;
val >>= 8;
size--;
} else {
@ -935,13 +906,13 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
}
/* check for complete packet */
if (s->loc[locty].w_offset > 5 &&
if (s->rw_offset > 5 &&
(s->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
/* we have a packet length - see if we have all of it */
bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);
len = tpm_tis_get_size_from_buffer(&s->loc[locty].w_buffer);
if (len > s->loc[locty].w_offset) {
len = tpm_cmd_get_size(&s->buffer);
if (len > s->rw_offset) {
tpm_tis_sts_set(&s->loc[locty],
TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
} else {
@ -974,20 +945,11 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
},
};
static int tpm_tis_do_startup_tpm(TPMState *s, uint32_t buffersize)
static int tpm_tis_do_startup_tpm(TPMState *s, size_t buffersize)
{
return tpm_backend_startup_tpm(s->be_driver, buffersize);
}
static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb,
size_t wanted_size)
{
if (sb->size != wanted_size) {
sb->buffer = g_realloc(sb->buffer, wanted_size);
sb->size = wanted_size;
}
}
/*
* Get the TPMVersion of the backend device being used
*/
@ -1012,7 +974,8 @@ static void tpm_tis_reset(DeviceState *dev)
int c;
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
s->be_buffer_size = tpm_backend_get_buffer_size(s->be_driver);
s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
TPM_TIS_BUFFER_MAX);
tpm_backend_reset(s->be_driver);
@ -1038,13 +1001,10 @@ static void tpm_tis_reset(DeviceState *dev)
s->loc[c].ints = 0;
s->loc[c].state = TPM_TIS_STATE_IDLE;
s->loc[c].w_offset = 0;
tpm_tis_realloc_buffer(&s->loc[c].w_buffer, s->be_buffer_size);
s->loc[c].r_offset = 0;
tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size);
s->rw_offset = 0;
}
tpm_tis_do_startup_tpm(s, 0);
tpm_tis_do_startup_tpm(s, s->be_buffer_size);
}
static const VMStateDescription vmstate_tpm_tis = {

View File

@ -355,3 +355,10 @@ int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version,
return 0;
}
void tpm_sized_buffer_reset(TPMSizedBuffer *tsb)
{
g_free(tsb->buffer);
tsb->buffer = NULL;
tsb->size = 0;
}

View File

@ -42,4 +42,11 @@ int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version,
#define DEFINE_PROP_TPMBE(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *)
typedef struct TPMSizedBuffer {
uint32_t size;
uint8_t *buffer;
} TPMSizedBuffer;
void tpm_sized_buffer_reset(TPMSizedBuffer *tsb);
#endif /* TPM_TPM_UTIL_H */

View File

@ -558,8 +558,8 @@ typedef struct Acpi20Tcpa Acpi20Tcpa;
/*
* TPM2
*
* Following Level 00, Rev 00.37 of specs:
* http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
* Following Version 1.2, Revision 8 of specs:
* https://trustedcomputinggroup.org/tcg-acpi-specification/
*/
struct Acpi20TPM2 {
ACPI_TABLE_HEADER_DEF
@ -567,6 +567,9 @@ struct Acpi20TPM2 {
uint16_t reserved;
uint64_t control_area_address;
uint32_t start_method;
uint8_t start_method_params[12];
uint32_t log_area_minimum_length;
uint64_t log_area_start_address;
} QEMU_PACKED;
typedef struct Acpi20TPM2 Acpi20TPM2;