diff options
Diffstat (limited to 'sys/dev/tpm')
| -rw-r--r-- | sys/dev/tpm/tpm20.c | 21 | ||||
| -rw-r--r-- | sys/dev/tpm/tpm20.h | 2 | ||||
| -rw-r--r-- | sys/dev/tpm/tpm_crb.c | 61 | ||||
| -rw-r--r-- | sys/dev/tpm/tpm_tis_core.c | 7 |
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); |
