From 0b4c7c65f882fac328f2c97398f06f16fe6d3f12 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 8 Nov 2017 15:30:18 -0500 Subject: [PATCH 01/10] tpm_emulator: Add a caching layer for the TPM Established flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a caching layer for the TPM established flag so that we don't need to go to the emulator every time the flag is read by accessing the REG_ACCESS register. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_emulator.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 38b6f175a1..35c78de5a9 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -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; } From 8a2306c7ed30bfc88cf7e3aced8c2867525f8d4b Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Nov 2017 20:32:06 -0500 Subject: [PATCH 02/10] tpm_tis: convert uint32_t to size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index b8e811b086..ac5f51f108 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -974,7 +974,7 @@ 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); } From 1af3d63ea3b0d18a6f17e4587f48529cd4fb26f0 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Nov 2017 19:24:02 -0500 Subject: [PATCH 03/10] tpm_tis: limit size of buffer from backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a preparatory patch for the subsequent ones where we get rid of the flexibility of supporting any kind of buffer size that the backend may support. We keep the size at 4096, which is also the size the external emulator supports. So, limit the size of the buffer we can support and pass it back to the backend. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index ac5f51f108..a6e2f6eb6c 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1012,7 +1012,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); @@ -1044,7 +1045,7 @@ static void tpm_tis_reset(DeviceState *dev) tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size); } - tpm_tis_do_startup_tpm(s, 0); + tpm_tis_do_startup_tpm(s, s->be_buffer_size); } static const VMStateDescription vmstate_tpm_tis = { From e6b703f6c7a88f84c62d9b8335ee8f451caa9bda Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Nov 2017 19:30:05 -0500 Subject: [PATCH 04/10] tpm_tis: remove TPMSizeBuffer usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove usage of TPMSizeBuffer. The size of the buffers is limited now by s->be_buffer_size, which is the size of the buffer the TIS has negotiated with the backend. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 68 +++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index a6e2f6eb6c..624c269189 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -64,8 +64,8 @@ typedef struct TPMLocality { uint16_t w_offset; uint16_t r_offset; - TPMSizedBuffer w_buffer; - TPMSizedBuffer r_buffer; + unsigned char w_buffer[TPM_TIS_BUFFER_MAX]; + unsigned char r_buffer[TPM_TIS_BUFFER_MAX]; } TPMLocality; typedef struct TPMState { @@ -215,23 +215,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 @@ -263,7 +259,8 @@ 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->loc[locty].w_buffer, s->be_buffer_size, + "tpm_tis: To TPM"); /* * w_offset serves as length indicator for length of data; @@ -273,10 +270,10 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) s->cmd = (TPMBackendCmd) { .locty = locty, - .in = locty_data->w_buffer.buffer, + .in = locty_data->w_buffer, .in_len = locty_data->w_offset, - .out = locty_data->r_buffer.buffer, - .out_len = locty_data->r_buffer.size + .out = locty_data->r_buffer, + .out_len = s->be_buffer_size, }; tpm_backend_deliver_request(s->be_driver, &s->cmd); @@ -427,7 +424,8 @@ static void tpm_tis_request_completed(TPMIf *ti) s->loc[locty].r_offset = 0; s->loc[locty].w_offset = 0; - tpm_tis_show_buffer(&s->loc[locty].r_buffer, "tpm_tis: From TPM"); + tpm_tis_show_buffer(s->loc[locty].r_buffer, s->be_buffer_size, + "tpm_tis: From TPM"); if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { tpm_tis_abort(s, locty); @@ -446,9 +444,10 @@ 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->loc[locty].r_buffer), + s->be_buffer_size); - ret = s->loc[locty].r_buffer.buffer[s->loc[locty].r_offset++]; + ret = s->loc[locty].r_buffer[s->loc[locty].r_offset++]; if (s->loc[locty].r_offset >= len) { /* got last byte */ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); @@ -494,11 +493,12 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "tpm_tis: result buffer : ", s->loc[locty].r_offset); for (idx = 0; - idx < tpm_tis_get_size_from_buffer(&s->loc[locty].r_buffer); + idx < MIN(tpm_cmd_get_size(&s->loc[locty].r_buffer), + s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].r_offset == idx ? '>' : ' ', - s->loc[locty].r_buffer.buffer[idx], + s->loc[locty].r_buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n" @@ -506,11 +506,12 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "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 < MIN(tpm_cmd_get_size(s->loc[locty].w_buffer), + s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].w_offset == idx ? '>' : ' ', - s->loc[locty].w_buffer.buffer[idx], + s->loc[locty].w_buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n"); @@ -572,11 +573,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) + MIN(tpm_cmd_get_size(&s->loc[locty].r_buffer), + s->be_buffer_size) - s->loc[locty].r_offset) | s->loc[locty].sts; } else { - avail = s->loc[locty].w_buffer.size - - s->loc[locty].w_offset; + avail = s->be_buffer_size - s->loc[locty].w_offset; /* * byte-sized reads should not return 0x00 for 0x100 * available bytes. @@ -924,9 +925,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->loc[locty].w_offset < s->be_buffer_size) { + s->loc[locty].w_buffer[s->loc[locty].w_offset++] = + (uint8_t)val; val >>= 8; size--; } else { @@ -940,7 +941,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, /* 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); + len = tpm_cmd_get_size(&s->loc[locty].w_buffer); if (len > s->loc[locty].w_offset) { tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); @@ -979,15 +980,6 @@ 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 */ @@ -1040,9 +1032,7 @@ static void tpm_tis_reset(DeviceState *dev) 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); } tpm_tis_do_startup_tpm(s, s->be_buffer_size); From 0804084230eaff79b4e00cf1c1bcfeb30e7bb9b4 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Nov 2017 20:01:46 -0500 Subject: [PATCH 05/10] tpm_tis: move buffers from localities into common location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One read buffer and one write buffer is sufficient for all localities. The localities cannot all be active at the same time, and only the active locality can use the r/w buffers. Inactive localities will require the COMMAND_READY flag to be set on the STS register to move to the READY state, which then enables access to using the buffer for writing of a command, while all other localities are inactive. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 624c269189..34bfc86143 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -64,16 +64,14 @@ typedef struct TPMLocality { uint16_t w_offset; uint16_t r_offset; - unsigned char w_buffer[TPM_TIS_BUFFER_MAX]; - unsigned char r_buffer[TPM_TIS_BUFFER_MAX]; } TPMLocality; typedef struct TPMState { ISADevice busdev; MemoryRegion mmio; - uint32_t offset; - uint8_t buf[TPM_TIS_BUFFER_MAX]; + unsigned char w_buffer[TPM_TIS_BUFFER_MAX]; + unsigned char r_buffer[TPM_TIS_BUFFER_MAX]; uint8_t active_locty; uint8_t aborting_locty; @@ -259,7 +257,7 @@ 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, s->be_buffer_size, + tpm_tis_show_buffer(s->w_buffer, s->be_buffer_size, "tpm_tis: To TPM"); /* @@ -270,9 +268,9 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) s->cmd = (TPMBackendCmd) { .locty = locty, - .in = locty_data->w_buffer, + .in = s->w_buffer, .in_len = locty_data->w_offset, - .out = locty_data->r_buffer, + .out = s->r_buffer, .out_len = s->be_buffer_size, }; @@ -424,7 +422,7 @@ static void tpm_tis_request_completed(TPMIf *ti) s->loc[locty].r_offset = 0; s->loc[locty].w_offset = 0; - tpm_tis_show_buffer(s->loc[locty].r_buffer, s->be_buffer_size, + tpm_tis_show_buffer(s->r_buffer, s->be_buffer_size, "tpm_tis: From TPM"); if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { @@ -444,10 +442,10 @@ 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 = MIN(tpm_cmd_get_size(&s->loc[locty].r_buffer), + len = MIN(tpm_cmd_get_size(&s->r_buffer), s->be_buffer_size); - ret = s->loc[locty].r_buffer[s->loc[locty].r_offset++]; + ret = s->r_buffer[s->loc[locty].r_offset++]; if (s->loc[locty].r_offset >= len) { /* got last byte */ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); @@ -493,12 +491,11 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "tpm_tis: result buffer : ", s->loc[locty].r_offset); for (idx = 0; - idx < MIN(tpm_cmd_get_size(&s->loc[locty].r_buffer), - s->be_buffer_size); + idx < MIN(tpm_cmd_get_size(&s->r_buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].r_offset == idx ? '>' : ' ', - s->loc[locty].r_buffer[idx], + s->r_buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n" @@ -506,12 +503,11 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "tpm_tis: request buffer: ", s->loc[locty].w_offset); for (idx = 0; - idx < MIN(tpm_cmd_get_size(s->loc[locty].w_buffer), - s->be_buffer_size); + idx < MIN(tpm_cmd_get_size(s->w_buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].w_offset == idx ? '>' : ' ', - s->loc[locty].w_buffer[idx], + s->w_buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n"); @@ -573,7 +569,7 @@ 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( - MIN(tpm_cmd_get_size(&s->loc[locty].r_buffer), + MIN(tpm_cmd_get_size(&s->r_buffer), s->be_buffer_size) - s->loc[locty].r_offset) | s->loc[locty].sts; } else { @@ -926,7 +922,7 @@ 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->be_buffer_size) { - s->loc[locty].w_buffer[s->loc[locty].w_offset++] = + s->w_buffer[s->loc[locty].w_offset++] = (uint8_t)val; val >>= 8; size--; @@ -941,7 +937,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, /* 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_cmd_get_size(&s->loc[locty].w_buffer); + len = tpm_cmd_get_size(&s->w_buffer); if (len > s->loc[locty].w_offset) { tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); From c5496b9797d8dfde3ef491da67b7a1d191820ef2 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 9 Nov 2017 20:12:39 -0500 Subject: [PATCH 06/10] tpm_tis: merge read and write buffer into single buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we can only be in read or write mode, we can merge the buffers into a single buffer. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 34bfc86143..ad3634789f 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -70,8 +70,7 @@ typedef struct TPMState { ISADevice busdev; MemoryRegion mmio; - unsigned char w_buffer[TPM_TIS_BUFFER_MAX]; - unsigned char r_buffer[TPM_TIS_BUFFER_MAX]; + unsigned char buffer[TPM_TIS_BUFFER_MAX]; uint8_t active_locty; uint8_t aborting_locty; @@ -257,7 +256,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) { TPMLocality *locty_data = &s->loc[locty]; - tpm_tis_show_buffer(s->w_buffer, s->be_buffer_size, + tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "tpm_tis: To TPM"); /* @@ -268,9 +267,9 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) s->cmd = (TPMBackendCmd) { .locty = locty, - .in = s->w_buffer, + .in = s->buffer, .in_len = locty_data->w_offset, - .out = s->r_buffer, + .out = s->buffer, .out_len = s->be_buffer_size, }; @@ -422,7 +421,7 @@ static void tpm_tis_request_completed(TPMIf *ti) s->loc[locty].r_offset = 0; s->loc[locty].w_offset = 0; - tpm_tis_show_buffer(s->r_buffer, s->be_buffer_size, + tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "tpm_tis: From TPM"); if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { @@ -442,10 +441,10 @@ 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 = MIN(tpm_cmd_get_size(&s->r_buffer), + len = MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); - ret = s->r_buffer[s->loc[locty].r_offset++]; + ret = s->buffer[s->loc[locty].r_offset++]; if (s->loc[locty].r_offset >= len) { /* got last byte */ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); @@ -491,11 +490,11 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "tpm_tis: result buffer : ", s->loc[locty].r_offset); for (idx = 0; - idx < MIN(tpm_cmd_get_size(&s->r_buffer), s->be_buffer_size); + idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].r_offset == idx ? '>' : ' ', - s->r_buffer[idx], + s->buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n" @@ -503,11 +502,11 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) "tpm_tis: request buffer: ", s->loc[locty].w_offset); for (idx = 0; - idx < MIN(tpm_cmd_get_size(s->w_buffer), s->be_buffer_size); + idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", s->loc[locty].w_offset == idx ? '>' : ' ', - s->w_buffer[idx], + s->buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n"); @@ -569,7 +568,7 @@ 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( - MIN(tpm_cmd_get_size(&s->r_buffer), + MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size) - s->loc[locty].r_offset) | s->loc[locty].sts; } else { @@ -922,7 +921,7 @@ 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->be_buffer_size) { - s->w_buffer[s->loc[locty].w_offset++] = + s->buffer[s->loc[locty].w_offset++] = (uint8_t)val; val >>= 8; size--; @@ -937,7 +936,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, /* 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_cmd_get_size(&s->w_buffer); + len = tpm_cmd_get_size(&s->buffer); if (len > s->loc[locty].w_offset) { tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); From e6b30c71f4b56784638eed475e7bdd6dc8c7764e Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 10 Nov 2017 07:37:27 -0500 Subject: [PATCH 07/10] tpm_tis: move r/w_offsets to TPMState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have a single buffer, we also only need a single set of read/write offsets into that buffer. This works since only one locality can be active. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 57 +++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index ad3634789f..45d7b8cf62 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -61,9 +61,6 @@ typedef struct TPMLocality { uint32_t iface_id; uint32_t inte; uint32_t ints; - - uint16_t w_offset; - uint16_t r_offset; } TPMLocality; typedef struct TPMState { @@ -71,6 +68,8 @@ typedef struct TPMState { MemoryRegion mmio; unsigned char buffer[TPM_TIS_BUFFER_MAX]; + uint16_t w_offset; + uint16_t r_offset; uint8_t active_locty; uint8_t aborting_locty; @@ -254,8 +253,6 @@ 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->buffer, s->be_buffer_size, "tpm_tis: To TPM"); @@ -268,7 +265,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) s->cmd = (TPMBackendCmd) { .locty = locty, .in = s->buffer, - .in_len = locty_data->w_offset, + .in_len = s->w_offset, .out = s->buffer, .out_len = s->be_buffer_size, }; @@ -350,8 +347,8 @@ 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->r_offset = 0; + s->w_offset = 0; DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", s->next_locty); @@ -418,8 +415,8 @@ 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->r_offset = 0; + s->w_offset = 0; tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "tpm_tis: From TPM"); @@ -444,14 +441,14 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) len = MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); - ret = s->buffer[s->loc[locty].r_offset++]; - if (s->loc[locty].r_offset >= len) { + ret = s->buffer[s->r_offset++]; + if (s->r_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->r_offset - 1); } return ret; @@ -488,24 +485,24 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) DPRINTF("tpm_tis: read offset : %d\n" "tpm_tis: result buffer : ", - s->loc[locty].r_offset); + s->r_offset); for (idx = 0; idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", - s->loc[locty].r_offset == idx ? '>' : ' ', + s->r_offset == idx ? '>' : ' ', s->buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } DPRINTF("\n" "tpm_tis: write offset : %d\n" "tpm_tis: request buffer: ", - s->loc[locty].w_offset); + s->w_offset); for (idx = 0; idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", - s->loc[locty].w_offset == idx ? '>' : ' ', + s->w_offset == idx ? '>' : ' ', s->buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } @@ -570,9 +567,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, val = TPM_TIS_BURST_COUNT( MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size) - - s->loc[locty].r_offset) | s->loc[locty].sts; + - s->r_offset) | s->loc[locty].sts; } else { - avail = s->be_buffer_size - s->loc[locty].w_offset; + avail = s->be_buffer_size - s->w_offset; /* * byte-sized reads should not return 0x00 for 0x100 * available bytes. @@ -836,8 +833,8 @@ 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->w_offset = 0; + s->r_offset = 0; break; case TPM_TIS_STATE_IDLE: @@ -855,8 +852,8 @@ 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->w_offset = 0; + s->r_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)) { @@ -882,7 +879,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->r_offset = 0; tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID| TPM_TIS_STS_DATA_AVAILABLE); @@ -920,8 +917,8 @@ 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->be_buffer_size) { - s->buffer[s->loc[locty].w_offset++] = + if (s->w_offset < s->be_buffer_size) { + s->buffer[s->w_offset++] = (uint8_t)val; val >>= 8; size--; @@ -931,13 +928,13 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, } /* check for complete packet */ - if (s->loc[locty].w_offset > 5 && + if (s->w_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_cmd_get_size(&s->buffer); - if (len > s->loc[locty].w_offset) { + if (len > s->w_offset) { tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); } else { @@ -1026,8 +1023,8 @@ 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; - s->loc[c].r_offset = 0; + s->w_offset = 0; + s->r_offset = 0; } tpm_tis_do_startup_tpm(s, s->be_buffer_size); From f999d81bc7d9ff3dd2b699d0091824e6b9071d83 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 10 Nov 2017 07:45:33 -0500 Subject: [PATCH 08/10] tpm_tis: merge r/w_offset into rw_offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can now merge the r_offset and w_offset into a single rw_offset. This is possible since when the offset is used for writing in RECEPTION state then reads are ignore. Conversely, when the offset is used for reading when in COMPLETION state, then writes are ignored. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 60 +++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 45d7b8cf62..ac5d5c61be 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -68,8 +68,7 @@ typedef struct TPMState { MemoryRegion mmio; unsigned char buffer[TPM_TIS_BUFFER_MAX]; - uint16_t w_offset; - uint16_t r_offset; + uint16_t rw_offset; uint8_t active_locty; uint8_t aborting_locty; @@ -257,7 +256,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) "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; @@ -265,7 +264,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) s->cmd = (TPMBackendCmd) { .locty = locty, .in = s->buffer, - .in_len = s->w_offset, + .in_len = s->rw_offset, .out = s->buffer, .out_len = s->be_buffer_size, }; @@ -347,8 +346,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->r_offset = 0; - s->w_offset = 0; + s->rw_offset = 0; DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", s->next_locty); @@ -415,8 +413,7 @@ 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->r_offset = 0; - s->w_offset = 0; + s->rw_offset = 0; tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "tpm_tis: From TPM"); @@ -441,14 +438,14 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) len = MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); - ret = s->buffer[s->r_offset++]; - if (s->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->r_offset - 1); + ret, s->rw_offset - 1); } return ret; @@ -483,26 +480,14 @@ 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->r_offset); + s->rw_offset); for (idx = 0; idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); idx++) { DPRINTF("%c%02x%s", - s->r_offset == idx ? '>' : ' ', - s->buffer[idx], - ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); - } - DPRINTF("\n" - "tpm_tis: write offset : %d\n" - "tpm_tis: request buffer: ", - s->w_offset); - for (idx = 0; - idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); - idx++) { - DPRINTF("%c%02x%s", - s->w_offset == idx ? '>' : ' ', + s->rw_offset == idx ? '>' : ' ', s->buffer[idx], ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); } @@ -567,9 +552,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, val = TPM_TIS_BURST_COUNT( MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size) - - s->r_offset) | s->loc[locty].sts; + - s->rw_offset) | s->loc[locty].sts; } else { - avail = s->be_buffer_size - s->w_offset; + avail = s->be_buffer_size - s->rw_offset; /* * byte-sized reads should not return 0x00 for 0x100 * available bytes. @@ -833,8 +818,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, switch (s->loc[locty].state) { case TPM_TIS_STATE_READY: - s->w_offset = 0; - s->r_offset = 0; + s->rw_offset = 0; break; case TPM_TIS_STATE_IDLE: @@ -852,8 +836,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, break; case TPM_TIS_STATE_COMPLETION: - s->w_offset = 0; - s->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)) { @@ -879,7 +862,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->r_offset = 0; + s->rw_offset = 0; tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID| TPM_TIS_STS_DATA_AVAILABLE); @@ -917,8 +900,8 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, } while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { - if (s->w_offset < s->be_buffer_size) { - s->buffer[s->w_offset++] = + if (s->rw_offset < s->be_buffer_size) { + s->buffer[s->rw_offset++] = (uint8_t)val; val >>= 8; size--; @@ -928,13 +911,13 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr, } /* check for complete packet */ - if (s->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_cmd_get_size(&s->buffer); - if (len > s->w_offset) { + if (len > s->rw_offset) { tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); } else { @@ -1023,8 +1006,7 @@ static void tpm_tis_reset(DeviceState *dev) s->loc[c].ints = 0; s->loc[c].state = TPM_TIS_STATE_IDLE; - s->w_offset = 0; - s->r_offset = 0; + s->rw_offset = 0; } tpm_tis_do_startup_tpm(s, s->be_buffer_size); From b86da7ddeda904b5fb1da03781328e7039536025 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 11 Oct 2017 10:36:53 -0400 Subject: [PATCH 09/10] tpm: Implement tpm_sized_buffer_reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the definition of TPMSizedBuffer out of tpm_tis.c into tpm_util.h and implement tpm_sized_buffer_reset() for the following patches to use. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/tpm/tpm_tis.c | 5 ----- hw/tpm/tpm_util.c | 7 +++++++ hw/tpm/tpm_util.h | 7 +++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index ac5d5c61be..561384cd86 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -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; diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c index 17cafbe6b3..747075e244 100644 --- a/hw/tpm/tpm_util.c +++ b/hw/tpm/tpm_util.c @@ -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; +} diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h index 2393b6bc0e..19b28474ae 100644 --- a/hw/tpm/tpm_util.h +++ b/hw/tpm/tpm_util.h @@ -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 */ From 4a42fa0ee20b51b326f6494cb50218b52471a261 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 14 Nov 2017 13:42:42 -0500 Subject: [PATCH 10/10] acpi: Update TPM2 ACPI table to more recent specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More recent specs of the TPM2 ACPI table add fields for the log area start address and the log area minimum size, which we already use for the TCPA table. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- hw/i386/acpi-build.c | 19 ++++++++++++++----- include/hw/acpi/acpi-defs.h | 7 +++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 5a6dee081c..18b939e469 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -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) { diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 72be675dd6..80c8099a23 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -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;