The branch main has been updated by jhibbits:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=10eea8dc8c4f3d2a3495e7fb08837d91adf465e9

commit 10eea8dc8c4f3d2a3495e7fb08837d91adf465e9
Author:     Justin Hibbits <[email protected]>
AuthorDate: 2024-05-09 19:27:35 +0000
Commit:     Justin Hibbits <[email protected]>
CommitDate: 2024-05-10 18:35:28 +0000

    tpm20: Support partial reads
    
    Summary:
    In some cases the TPM utilities may read only a partial block, instead
    of a full block.  If a new command starts while in the middle of a read
    it may cause the TPM to go catatonic and no longer respond to SPI.
    
    Reviewed by:    kd
    Obtained from:  Juniper Networks, Inc.
    Differential Revision: https://reviews.freebsd.org/D45140
---
 sys/dev/tpm/tpm20.c        | 10 +++++++---
 sys/dev/tpm/tpm20.h        |  1 +
 sys/dev/tpm/tpm_crb.c      |  1 +
 sys/dev/tpm/tpm_tis_core.c |  1 +
 4 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
index 3399e17f53aa..80f7d9e105a6 100644
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -68,6 +68,7 @@ tpm20_read(struct cdev *dev, struct uio *uio, int flags)
 {
        struct tpm_sc *sc;
        size_t bytes_to_transfer;
+       size_t offset;
        int result = 0;
 
        sc = (struct tpm_sc *)dev->si_drv1;
@@ -80,10 +81,10 @@ tpm20_read(struct cdev *dev, struct uio *uio, int flags)
        }
 
        bytes_to_transfer = MIN(sc->pending_data_length, uio->uio_resid);
+       offset = sc->total_length - sc->pending_data_length;
        if (bytes_to_transfer > 0) {
-               result = uiomove((caddr_t) sc->buf, bytes_to_transfer, uio);
-               memset(sc->buf, 0, TPM_BUFSIZE);
-               sc->pending_data_length = 0;
+               result = uiomove((caddr_t) sc->buf + offset, bytes_to_transfer, 
uio);
+               sc->pending_data_length -= bytes_to_transfer;
                cv_signal(&sc->buf_cv);
        } else {
                result = ETIMEDOUT;
@@ -152,6 +153,7 @@ tpm20_discard_buffer(void *arg)
 
        memset(sc->buf, 0, TPM_BUFSIZE);
        sc->pending_data_length = 0;
+       sc->total_length = 0;
 
        cv_signal(&sc->buf_cv);
        sx_xunlock(&sc->dev_lock);
@@ -191,6 +193,7 @@ tpm20_init(struct tpm_sc *sc)
        cv_init(&sc->buf_cv, "TPM buffer cv");
        callout_init(&sc->discard_buffer_callout, 1);
        sc->pending_data_length = 0;
+       sc->total_length = 0;
 
        make_dev_args_init(&args);
        args.mda_devsw = &tpm20_cdevsw;
@@ -275,6 +278,7 @@ tpm20_harvest(void *arg, int unused)
 
        /* Ignore response size */
        sc->pending_data_length = 0;
+       sc->total_length = 0;
 
        /* The number of random bytes we got is placed right after the header */
        entropy_size = (uint16_t) sc->buf[TPM_HEADER_SIZE + 1];
diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h
index 683cd7549bd4..7c2ccd30143a 100644
--- a/sys/dev/tpm/tpm20.h
+++ b/sys/dev/tpm/tpm20.h
@@ -124,6 +124,7 @@ struct tpm_sc {
 
        uint8_t         *buf;
        size_t          pending_data_length;
+       size_t          total_length;
        lwpid_t         owner_tid;
 
        struct callout  discard_buffer_callout;
diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c
index b9ddcf0dd3e1..017ebd45c7ea 100644
--- a/sys/dev/tpm/tpm_crb.c
+++ b/sys/dev/tpm/tpm_crb.c
@@ -398,6 +398,7 @@ tpmcrb_transmit(device_t dev, size_t length)
 
        tpmcrb_relinquish_locality(sc);
        sc->pending_data_length = bytes_available;
+       sc->total_length = bytes_available;
 
        return (0);
 }
diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c
index 230eb12d2acd..d8421f8156c9 100644
--- a/sys/dev/tpm/tpm_tis_core.c
+++ b/sys/dev/tpm/tpm_tis_core.c
@@ -469,6 +469,7 @@ tpmtis_transmit(device_t dev, size_t length)
        }
        tpmtis_relinquish_locality(sc);
        sc->pending_data_length = bytes_available;
+       sc->total_length = bytes_available;
 
        return (0);
 }

Reply via email to