aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/tpm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/tpm')
-rw-r--r--sys/dev/tpm/tpm20.c21
-rw-r--r--sys/dev/tpm/tpm20.h2
-rw-r--r--sys/dev/tpm/tpm_crb.c61
-rw-r--r--sys/dev/tpm/tpm_tis_core.c7
4 files changed, 72 insertions, 19 deletions
diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
index 876dd0bcc40d..6c587818058d 100644
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -25,8 +25,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include <sys/random.h>
+#include <dev/random/randomdev.h>
#include "tpm20.h"
@@ -42,7 +42,7 @@
MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver");
static void tpm20_discard_buffer(void *arg);
-#ifdef TPM_HARVEST
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
static void tpm20_harvest(void *arg, int unused);
#endif
static int tpm20_save_state(device_t dev, bool suspend);
@@ -184,6 +184,13 @@ tpm20_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
return (ENOTTY);
}
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
+static const struct random_source random_tpm = {
+ .rs_ident = "TPM",
+ .rs_source = RANDOM_PURE_TPM,
+};
+#endif
+
int
tpm20_init(struct tpm_sc *sc)
{
@@ -205,8 +212,8 @@ tpm20_init(struct tpm_sc *sc)
if (result != 0)
tpm20_release(sc);
-#ifdef TPM_HARVEST
- random_harvest_register_source(RANDOM_PURE_TPM);
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
+ random_source_register(&random_tpm);
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0,
tpm20_harvest, sc);
taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0);
@@ -220,10 +227,10 @@ void
tpm20_release(struct tpm_sc *sc)
{
-#ifdef TPM_HARVEST
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
if (device_is_attached(sc->dev))
taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
- random_harvest_deregister_source(RANDOM_PURE_TPM);
+ random_source_deregister(&random_tpm);
#endif
if (sc->buf != NULL)
@@ -247,7 +254,7 @@ tpm20_shutdown(device_t dev)
return (tpm20_save_state(dev, false));
}
-#ifdef TPM_HARVEST
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
/*
* Get TPM_HARVEST_SIZE random bytes and add them
* into system entropy pool.
diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h
index 7c2ccd30143a..b2cfcd4f25bd 100644
--- a/sys/dev/tpm/tpm20.h
+++ b/sys/dev/tpm/tpm20.h
@@ -128,7 +128,7 @@ struct tpm_sc {
lwpid_t owner_tid;
struct callout discard_buffer_callout;
-#ifdef TPM_HARVEST
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
struct timeout_task harvest_task;
#endif
diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c
index 017ebd45c7ea..28b4f21eccfb 100644
--- a/sys/dev/tpm/tpm_crb.c
+++ b/sys/dev/tpm/tpm_crb.c
@@ -301,6 +301,48 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc)
return (true);
}
+static bool
+tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait)
+{
+ struct tpm_sc *sc;
+ int mask, timeout;
+
+ timeout = wait ? TPM_TIMEOUT_C : 0;
+
+ sc = &crb_sc->base;
+ OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
+
+ if (timeout > 0) {
+ mask = TPM_CRB_CTRL_STS_IDLE_BIT;
+ if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, mask,
+ timeout))
+ return (false);
+ }
+
+ return (true);
+}
+
+static bool
+tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait)
+{
+ struct tpm_sc *sc;
+ int mask, timeout;
+
+ timeout = wait ? TPM_TIMEOUT_C : 0;
+
+ sc = &crb_sc->base;
+ OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
+
+ if (timeout > 0) {
+ mask = TPM_CRB_CTRL_REQ_GO_READY;
+ if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, !mask,
+ timeout))
+ return (false);
+ }
+
+ return (true);
+}
+
int
tpmcrb_transmit(device_t dev, size_t length)
{
@@ -335,22 +377,15 @@ tpmcrb_transmit(device_t dev, size_t length)
/* Switch device to idle state if necessary */
if (!(TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
-
- mask = TPM_CRB_CTRL_STS_IDLE_BIT;
- if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
- mask, mask, TPM_TIMEOUT_C)) {
+ if (!tpmcrb_state_idle(crb_sc, true)) {
device_printf(dev,
"Failed to transition to idle state\n");
return (EIO);
}
}
- /* Switch to ready state */
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
- mask = TPM_CRB_CTRL_REQ_GO_READY;
- if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
- mask, !mask, TPM_TIMEOUT_C)) {
+ /* Switch to ready state */
+ if (!tpmcrb_state_ready(crb_sc, true)) {
device_printf(dev,
"Failed to transition to ready state\n");
return (EIO);
@@ -394,7 +429,11 @@ tpmcrb_transmit(device_t dev, size_t length)
bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
&sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
+ if (!tpmcrb_state_idle(crb_sc, false)) {
+ device_printf(dev,
+ "Failed to transition to idle state post-send\n");
+ return (EIO);
+ }
tpmcrb_relinquish_locality(sc);
sc->pending_data_length = bytes_available;
diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c
index d8421f8156c9..4159de4daf3b 100644
--- a/sys/dev/tpm/tpm_tis_core.c
+++ b/sys/dev/tpm/tpm_tis_core.c
@@ -97,6 +97,7 @@ tpmtis_attach(device_t dev)
{
struct tpm_sc *sc;
int result;
+ int poll = 0;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -105,6 +106,12 @@ tpmtis_attach(device_t dev)
sx_init(&sc->dev_lock, "TPM driver lock");
sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK);
+ resource_int_value("tpm", device_get_unit(dev), "use_polling", &poll);
+ if (poll != 0) {
+ device_printf(dev, "Using poll method to get TPM operation status \n");
+ goto skip_irq;
+ }
+
sc->irq_rid = 0;
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
RF_ACTIVE | RF_SHAREABLE);