Commit 116694c3 authored by Stefan Berger's avatar Stefan Berger Committed by Michael S. Tsirkin
Browse files

Extend TPM TIS interface to support TPM 2



Following the recent upgrade to version 1.3, extend the TPM TIS
interface with capabilities introduced for support of a TPM 2.

TPM TIS for TPM 2 introduced the following extensions beyond the
TPM TIS 1.3 (used for TPM 1.2):

- A new 32bit interface Id register was introduced.
- New flags for the status (STS) register were defined.
- New flags for the capability flags were defined.

Support the above if a TPM TIS 1.3 for TPM 2 is used with a TPM 2
on the backend side. Support the old TPM TIS 1.3 configuration if a
TPM 1.2 is being used. A subsequent patch will then determine which
TPM version is being used in the backend.

Signed-off-by: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 38d40ff1
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -96,6 +96,20 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
    return k->ops->get_tpm_established_flag(s);
}

int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
{
    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);

    return k->ops->reset_tpm_established_flag(s, locty);
}

TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
{
    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);

    return k->ops->get_tpm_version(s);
}

static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
{
    TPMBackend *s = TPM_BACKEND(obj);
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ struct TPMState {

    char *backend;
    TPMBackend *be_driver;
    TPMVersion be_tpm_version;
};

#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
+14 −0
Original line number Diff line number Diff line
@@ -267,6 +267,13 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
    return false;
}

static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
                                                      uint8_t locty)
{
    /* only a TPM 2.0 will support this */
    return 0;
}

static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
{
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -324,6 +331,11 @@ static const char *tpm_passthrough_create_desc(void)
    return "Passthrough TPM backend driver";
}

static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
{
    return TPM_VERSION_1_2;
}

/*
 * A basic test of a TPM device. We expect a well formatted response header
 * (error response is fine) within one second.
@@ -540,6 +552,8 @@ static const TPMDriverOps tpm_passthrough_driver = {
    .deliver_request          = tpm_passthrough_deliver_request,
    .cancel_cmd               = tpm_passthrough_cancel_cmd,
    .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
    .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
    .get_tpm_version          = tpm_passthrough_get_tpm_version,
};

static void tpm_passthrough_inst_init(Object *obj)
+99 −9
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
 * supports version 1.3, 21 March 2013
 * In the developers menu choose the PC Client section then find the TIS
 * specification.
 *
 * TPM TIS for TPM 2 implementation following TCG PC Client Platform
 * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43
 */

#include "sysemu/tpm_backend.h"
@@ -49,6 +52,7 @@
#define TPM_TIS_REG_INTF_CAPABILITY       0x14
#define TPM_TIS_REG_STS                   0x18
#define TPM_TIS_REG_DATA_FIFO             0x24
#define TPM_TIS_REG_INTERFACE_ID          0x30
#define TPM_TIS_REG_DATA_XFIFO            0x80
#define TPM_TIS_REG_DATA_XFIFO_END        0xbc
#define TPM_TIS_REG_DID_VID               0xf00
@@ -57,6 +61,12 @@
/* vendor-specific registers */
#define TPM_TIS_REG_DEBUG                 0xf90

#define TPM_TIS_STS_TPM_FAMILY_MASK         (0x3 << 26)/* TPM 2.0 */
#define TPM_TIS_STS_TPM_FAMILY1_2           (0 << 26)  /* TPM 2.0 */
#define TPM_TIS_STS_TPM_FAMILY2_0           (1 << 26)  /* TPM 2.0 */
#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25)  /* TPM 2.0 */
#define TPM_TIS_STS_COMMAND_CANCEL          (1 << 24)  /* TPM 2.0 */

#define TPM_TIS_STS_VALID                 (1 << 7)
#define TPM_TIS_STS_COMMAND_READY         (1 << 6)
#define TPM_TIS_STS_TPM_GO                (1 << 5)
@@ -102,16 +112,43 @@
#endif

#define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28)
#define TPM_TIS_CAP_DATA_TRANSFER_64B    (3 << 9)
#define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
#define TPM_TIS_CAP_BURST_COUNT_DYNAMIC  (0 << 8)
#define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL  (1 << 4) /* support is mandatory */
#define TPM_TIS_CAPABILITIES_SUPPORTED   (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \
    (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
     TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
     TPM_TIS_CAP_DATA_TRANSFER_64B | \
     TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
     TPM_TIS_INTERRUPTS_SUPPORTED)

#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \
    (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
     TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
     TPM_TIS_CAP_DATA_TRANSFER_64B | \
     TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \
     TPM_TIS_INTERRUPTS_SUPPORTED)

#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3   (0xf)     /* TPM 2.0 */
#define TPM_TIS_IFACE_ID_INTERFACE_FIFO     (0x0)     /* TPM 2.0 */
#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4)  /* TPM 2.0 */
#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES   (1 << 8)  /* TPM 2.0 */
#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED  (1 << 13) /* TPM 2.0 */
#define TPM_TIS_IFACE_ID_INT_SEL_LOCK       (1 << 19) /* TPM 2.0 */

#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \
    (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \
     (~0 << 4)/* all of it is don't care */)

/* if backend was a TPM 2.0: */
#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \
    (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \
     TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \
     TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \
     TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED)

#define TPM_TIS_TPM_DID       0x0001
#define TPM_TIS_TPM_VID       PCI_VENDOR_ID_IBM
#define TPM_TIS_TPM_RID       0x0001
@@ -154,7 +191,8 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)

/*
 * Set the given flags in the STS register by clearing the register but
 * preserving the SELFTEST_DONE flag and then setting the new flags.
 * preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting
 * the new flags.
 *
 * The SELFTEST_DONE flag is acquired from the backend that determines it by
 * peeking into TPM commands.
@@ -166,7 +204,7 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
 */
static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
{
    l->sts &= TPM_TIS_STS_SELFTEST_DONE;
    l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK;
    l->sts |= flags;
}

@@ -489,7 +527,17 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
        val = tis->loc[locty].ints;
        break;
    case TPM_TIS_REG_INTF_CAPABILITY:
        val = TPM_TIS_CAPABILITIES_SUPPORTED;
        switch (s->be_tpm_version) {
        case TPM_VERSION_UNSPEC:
            val = 0;
            break;
        case TPM_VERSION_1_2:
            val = TPM_TIS_CAPABILITIES_SUPPORTED1_3;
            break;
        case TPM_VERSION_2_0:
            val = TPM_TIS_CAPABILITIES_SUPPORTED2_0;
            break;
        }
        break;
    case TPM_TIS_REG_STS:
        if (tis->active_locty == locty) {
@@ -536,6 +584,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
            shift = 0; /* no more adjustments */
        }
        break;
    case TPM_TIS_REG_INTERFACE_ID:
        val = tis->loc[locty].iface_id;
        break;
    case TPM_TIS_REG_DID_VID:
        val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
        break;
@@ -736,6 +787,25 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
            break;
        }

        if (s->be_tpm_version == TPM_VERSION_2_0) {
            /* some flags that are only supported for TPM 2 */
            if (val & TPM_TIS_STS_COMMAND_CANCEL) {
                if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) {
                    /*
                     * request the backend to cancel. Some backends may not
                     * support it
                     */
                    tpm_backend_cancel_cmd(s->be_driver);
                }
            }

            if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) {
                if (locty == 3 || locty == 4) {
                    tpm_backend_reset_tpm_established_flag(s->be_driver, locty);
                }
            }
        }

        val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
                TPM_TIS_STS_RESPONSE_RETRY);

@@ -860,6 +930,13 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
            }
        }
        break;
    case TPM_TIS_REG_INTERFACE_ID:
        if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) {
            for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
                tis->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK;
            }
        }
        break;
    }
}

@@ -894,6 +971,8 @@ static void tpm_tis_reset(DeviceState *dev)
    TPMTISEmuState *tis = &s->s.tis;
    int c;

    s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);

    tpm_backend_reset(s->be_driver);

    tis->active_locty = TPM_TIS_NO_LOCALITY;
@@ -902,7 +981,18 @@ static void tpm_tis_reset(DeviceState *dev)

    for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
        tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
        tis->loc[c].sts = 0;
        switch (s->be_tpm_version) {
        case TPM_VERSION_UNSPEC:
            break;
        case TPM_VERSION_1_2:
            tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2;
            tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3;
            break;
        case TPM_VERSION_2_0:
            tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0;
            tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0;
            break;
        }
        tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
        tis->loc[c].ints = 0;
        tis->loc[c].state = TPM_TIS_STATE_IDLE;
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ typedef struct TPMLocality {
    TPMTISState state;
    uint8_t access;
    uint32_t sts;
    uint32_t iface_id;
    uint32_t inte;
    uint32_t ints;

Loading