mirror of https://gitee.com/openkylin/qemu.git
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:
commit
b1e513ae33
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
130
hw/tpm/tpm_tis.c
130
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;
|
||||
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue