git: 10eea8dc8c4f - main - tpm20: Support partial reads
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 10 May 2024 14:36:13 UTC
The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=10eea8dc8c4f3d2a3495e7fb08837d91adf465e9 commit 10eea8dc8c4f3d2a3495e7fb08837d91adf465e9 Author: Justin Hibbits <jhibbits@FreeBSD.org> AuthorDate: 2024-05-09 19:27:35 +0000 Commit: Justin Hibbits <jhibbits@FreeBSD.org> 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); }