Page MenuHomeFreeBSD

D59240.id185293.diff
No OneTemporary

D59240.id185293.diff

Index: sys/dev/tpm/tpm20.h
===================================================================
--- sys/dev/tpm/tpm20.h
+++ sys/dev/tpm/tpm20.h
@@ -128,6 +128,8 @@
uint32_t intr_mask; /* Saved TIS interrupt configuration */
bool interrupts;
bool common_initialized;
+ bool dying;
+ bool suspended;
struct tpm_priv *internal_priv;
Index: sys/dev/tpm/tpm20.c
===================================================================
--- sys/dev/tpm/tpm20.c
+++ sys/dev/tpm/tpm20.c
@@ -87,12 +87,22 @@
struct tpm_priv *priv;
size_t bytes_to_transfer;
size_t offset;
- int result = 0;
+ int result;
sc = (struct tpm_sc *)dev->si_drv1;
- devfs_get_cdevpriv((void **)&priv);
+ result = devfs_get_cdevpriv((void **)&priv);
+ if (result != 0)
+ return (result);
sx_xlock(&sc->dev_lock);
+ if (sc->dying) {
+ result = ENXIO;
+ goto out;
+ }
+ if (sc->suspended) {
+ result = EBUSY;
+ goto out;
+ }
offset = priv->offset;
bytes_to_transfer = MIN(priv->len, uio->uio_resid);
if (bytes_to_transfer > 0) {
@@ -103,8 +113,8 @@
result = 0;
}
+out:
sx_xunlock(&sc->dev_lock);
-
return (result);
}
@@ -114,10 +124,12 @@
struct tpm_sc *sc;
struct tpm_priv *priv;
size_t byte_count;
- int result = 0;
+ int result;
sc = (struct tpm_sc *)dev->si_drv1;
- devfs_get_cdevpriv((void **)&priv);
+ result = devfs_get_cdevpriv((void **)&priv);
+ if (result != 0)
+ return (result);
byte_count = uio->uio_resid;
if (byte_count < TPM_HEADER_SIZE) {
@@ -133,15 +145,22 @@
}
sx_xlock(&sc->dev_lock);
+ if (sc->dying) {
+ result = ENXIO;
+ goto out;
+ }
+ if (sc->suspended) {
+ result = EBUSY;
+ goto out;
+ }
result = uiomove(priv->buf, byte_count, uio);
- if (result != 0) {
- sx_xunlock(&sc->dev_lock);
- return (result);
- }
+ if (result != 0)
+ goto out;
result = TPM_TRANSMIT(sc->dev, priv, byte_count);
+out:
sx_xunlock(&sc->dev_lock);
return (result);
}
@@ -166,12 +185,28 @@
int
tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td)
{
+ struct tpm_sc *sc;
struct tpm_priv *priv;
+ int error;
+ sc = (struct tpm_sc *)dev->si_drv1;
+ sx_xlock(&sc->dev_lock);
+ if (sc->dying) {
+ error = ENXIO;
+ goto out;
+ }
+ if (sc->suspended) {
+ error = EBUSY;
+ goto out;
+ }
priv = tpm20_priv_alloc();
- devfs_set_cdevpriv(priv, tpm20_priv_dtor);
+ error = devfs_set_cdevpriv(priv, tpm20_priv_dtor);
+ if (error != 0)
+ tpm20_priv_dtor(priv);
- return (0);
+out:
+ sx_xunlock(&sc->dev_lock);
+ return (error);
}
int
@@ -202,6 +237,8 @@
struct make_dev_args args;
int result;
+ sc->dying = false;
+ sc->suspended = false;
sc->internal_priv = tpm20_priv_alloc();
make_dev_args_init(&args);
@@ -230,11 +267,19 @@
tpm20_release(struct tpm_sc *sc)
{
+ sx_xlock(&sc->dev_lock);
+ sc->dying = true;
+ sx_xunlock(&sc->dev_lock);
+
+ /* Stop and drain character-device methods before freeing their state. */
+ if (sc->sc_cdev != NULL) {
+ destroy_dev(sc->sc_cdev);
+ sc->sc_cdev = NULL;
+ }
if (!sc->common_initialized)
goto out;
#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
- if (device_is_attached(sc->dev))
- taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
+ taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
random_source_deregister(&random_tpm);
#endif
sc->common_initialized = false;
@@ -244,25 +289,29 @@
sc->internal_priv = NULL;
}
sx_destroy(&sc->dev_lock);
- if (sc->sc_cdev != NULL) {
- destroy_dev(sc->sc_cdev);
- sc->sc_cdev = NULL;
- }
}
int
tpm20_resume(device_t dev)
{
+ struct tpm_sc *sc;
int error;
+ sc = device_get_softc(dev);
+ sx_xlock(&sc->dev_lock);
+ if (sc->dying) {
+ error = ENXIO;
+ goto out;
+ }
error = tpm20_restart(dev, false);
+ if (error == 0)
+ sc->suspended = false;
+out:
+ sx_xunlock(&sc->dev_lock);
if (error != 0)
return (error);
#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
- struct tpm_sc *sc;
-
- sc = device_get_softc(dev);
taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
hz * TPM_HARVEST_INTERVAL);
#endif
@@ -272,15 +321,27 @@
int
tpm20_suspend(device_t dev)
{
- int error;
-
-#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
struct tpm_sc *sc;
+ int error;
sc = device_get_softc(dev);
+#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
#endif
+ sx_xlock(&sc->dev_lock);
+ if (sc->dying) {
+ error = ENXIO;
+ goto out;
+ }
+ if (sc->suspended) {
+ error = 0;
+ goto out;
+ }
error = tpm20_save_state(dev, true);
+ if (error == 0)
+ sc->suspended = true;
+out:
+ sx_xunlock(&sc->dev_lock);
#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
if (error != 0)
taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
@@ -292,7 +353,17 @@
int
tpm20_shutdown(device_t dev)
{
- return (tpm20_save_state(dev, false));
+ struct tpm_sc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sx_xlock(&sc->dev_lock);
+ if (sc->dying)
+ error = ENXIO;
+ else
+ error = tpm20_save_state(dev, false);
+ sx_xunlock(&sc->dev_lock);
+ return (error);
}
#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
@@ -317,31 +388,32 @@
sc = arg;
sx_xlock(&sc->dev_lock);
+ if (sc->dying || sc->suspended) {
+ sx_xunlock(&sc->dev_lock);
+ return;
+ }
priv = sc->internal_priv;
memcpy(priv->buf, cmd, sizeof(cmd));
+ entropy_size = 0;
result = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd));
- if (result != 0) {
- sx_xunlock(&sc->dev_lock);
- return;
- }
-
- /* The number of random bytes we got is placed right after the header */
- entropy_size = (uint16_t) priv->buf[TPM_HEADER_SIZE + 1];
- if (entropy_size > 0) {
- entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
- memcpy(entropy,
- priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
- entropy_size);
+ if (result == 0) {
+ /* The byte count is placed immediately after the header. */
+ entropy_size = (uint16_t)priv->buf[TPM_HEADER_SIZE + 1];
+ if (entropy_size > 0) {
+ entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
+ memcpy(entropy,
+ priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
+ entropy_size);
+ }
}
+ taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
+ hz * TPM_HARVEST_INTERVAL);
sx_xunlock(&sc->dev_lock);
if (entropy_size > 0)
random_harvest_queue(entropy, entropy_size, RANDOM_PURE_TPM);
-
- taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
- hz * TPM_HARVEST_INTERVAL);
}
#endif /* TPM_HARVEST */
@@ -367,7 +439,9 @@
be32enc(cmd + 6, command);
be16enc(cmd + 10, parameter);
- sx_xlock(&sc->dev_lock);
+ sx_assert(&sc->dev_lock, SA_XLOCKED);
+ if (sc->dying)
+ return (ENXIO);
priv = sc->internal_priv;
delay_ms = TPM2_RETRY_INITIAL_MS;
for (;;) {
@@ -393,13 +467,9 @@
break;
if (delay_ms > TPM2_RETRY_MAX_MS)
break;
- sx_xunlock(&sc->dev_lock);
pause("tpm2retry", MAX(hz * delay_ms / 1000, 1));
- sx_xlock(&sc->dev_lock);
delay_ms *= 2;
}
- sx_xunlock(&sc->dev_lock);
-
if (error != 0) {
device_printf(dev, "%s command failed: %d\n", name, error);
return (error);

File Metadata

Mime Type
text/plain
Expires
Tue, Sep 8, 2:30 PM (2 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38450596
Default Alt Text
D59240.id185293.diff (6 KB)

Event Timeline