diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h --- a/sys/dev/tpm/tpm20.h +++ b/sys/dev/tpm/tpm20.h @@ -124,6 +124,7 @@ 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/tpm20.c b/sys/dev/tpm/tpm20.c --- a/sys/dev/tpm/tpm20.c +++ b/sys/dev/tpm/tpm20.c @@ -68,6 +68,7 @@ { 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 @@ } 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 @@ 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 @@ 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 @@ /* 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/tpm_crb.c b/sys/dev/tpm/tpm_crb.c --- a/sys/dev/tpm/tpm_crb.c +++ b/sys/dev/tpm/tpm_crb.c @@ -398,6 +398,7 @@ 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 --- a/sys/dev/tpm/tpm_tis_core.c +++ b/sys/dev/tpm/tpm_tis_core.c @@ -469,6 +469,7 @@ } tpmtis_relinquish_locality(sc); sc->pending_data_length = bytes_available; + sc->total_length = bytes_available; return (0); }