Module Name: src Committed By: maxv Date: Wed Oct 9 07:30:58 UTC 2019
Modified Files: src/sys/dev/acpi: tpm_acpi.c src/sys/dev/ic: tpm.c tpmreg.h tpmvar.h src/sys/dev/isa: tpm_isa.c Log Message: Add suspend support for TPM 2.0 chips. Check the TPM response also for 1.2 chips. Unfortunately I cannot really test this change since ACPI suspend does not work on any of my laptops. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/dev/acpi/tpm_acpi.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/tpm.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/tpmreg.h src/sys/dev/ic/tpmvar.h cvs rdiff -u -r1.5 -r1.6 src/sys/dev/isa/tpm_isa.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/tpm_acpi.c diff -u src/sys/dev/acpi/tpm_acpi.c:1.9 src/sys/dev/acpi/tpm_acpi.c:1.10 --- src/sys/dev/acpi/tpm_acpi.c:1.9 Tue Oct 8 18:43:02 2019 +++ src/sys/dev/acpi/tpm_acpi.c Wed Oct 9 07:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $ */ +/* $NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $ */ /* * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.10 2019/10/09 07:30:58 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -148,6 +148,8 @@ tpm_acpi_attach(device_t parent, device_ goto out1; } + if (!pmf_device_register(self, tpm_suspend, tpm_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); acpi_resource_cleanup(&res); return; Index: src/sys/dev/ic/tpm.c diff -u src/sys/dev/ic/tpm.c:1.14 src/sys/dev/ic/tpm.c:1.15 --- src/sys/dev/ic/tpm.c:1.14 Tue Oct 8 18:43:02 2019 +++ src/sys/dev/ic/tpm.c Wed Oct 9 07:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $ */ +/* $NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.15 2019/10/09 07:30:58 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -65,8 +65,9 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 #include "ioconf.h" +CTASSERT(sizeof(struct tpm_header) == 10); + #define TPM_BUFSIZ 1024 -#define TPM_HDRSIZE 10 #define TPM_PARAM_SIZE 0x0001 /* that's a flag */ @@ -163,31 +164,69 @@ tpm_status(struct tpm_softc *sc) /* -------------------------------------------------------------------------- */ -/* - * Save TPM state on suspend. On resume we don't do anything, since the BIOS - * is supposed to restore the previously saved state. - */ +static bool +tpm12_suspend(struct tpm_softc *sc) +{ + static const uint8_t command[10] = { + 0x00, 0xC1, /* TPM_TAG_RQU_COMMAND */ + 0x00, 0x00, 0x00, 10, /* Length in bytes */ + 0x00, 0x00, 0x00, 0x98 /* TPM_ORD_SaveState */ + }; + struct tpm_header response; -bool -tpm12_suspend(device_t dev, const pmf_qual_t *qual) + if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0) + return false; + if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0) + return false; + if (TPM_BE32(response.code) != 0) + return false; + + return true; +} + +static bool +tpm20_suspend(struct tpm_softc *sc) { - struct tpm_softc *sc = device_private(dev); - static const uint8_t command[] = { - 0, 0xC1, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 10, /* Length in bytes */ - 0, 0, 0, 0x98 /* TPM_ORD_SaveState */ + static const uint8_t command[12] = { + 0x80, 0x01, /* TPM_ST_NO_SESSIONS */ + 0x00, 0x00, 0x00, 12, /* Length in bytes */ + 0x00, 0x00, 0x01, 0x45, /* TPM_CC_Shutdown */ + 0x00, 0x01 /* TPM_SU_STATE */ }; - uint8_t scratch[sizeof(command)]; + struct tpm_header response; - (*sc->sc_write)(sc, &command, sizeof(command)); - (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0); + if ((*sc->sc_write)(sc, &command, sizeof(command)) != 0) + return false; + if ((*sc->sc_read)(sc, &response, sizeof(response), NULL, 0) != 0) + return false; + if (TPM_BE32(response.code) != 0) + return false; return true; } bool -tpm12_resume(device_t dev, const pmf_qual_t *qual) +tpm_suspend(device_t dev, const pmf_qual_t *qual) { + struct tpm_softc *sc = device_private(dev); + + switch (sc->sc_ver) { + case TPM_1_2: + return tpm12_suspend(sc); + case TPM_2_0: + return tpm20_suspend(sc); + default: + panic("%s: impossible", __func__); + } +} + +bool +tpm_resume(device_t dev, const pmf_qual_t *qual) +{ + /* + * Don't do anything, the BIOS is supposed to restore the previously + * saved state. + */ return true; } @@ -508,6 +547,7 @@ static int tpmread(dev_t dev, struct uio *uio, int flags) { struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev)); + struct tpm_header hdr; uint8_t buf[TPM_BUFSIZ]; size_t cnt, len, n; int rv; @@ -519,11 +559,11 @@ tpmread(dev_t dev, struct uio *uio, int goto out; /* Get the header. */ - if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) { + if ((rv = (*sc->sc_read)(sc, &hdr, sizeof(hdr), &cnt, 0))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } - len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5]; + len = TPM_BE32(hdr.length); if (len > uio->uio_resid || len < cnt) { rv = EIO; (*sc->sc_end)(sc, UIO_READ, rv); @@ -531,7 +571,7 @@ tpmread(dev_t dev, struct uio *uio, int } /* Copy out the header. */ - if ((rv = uiomove(buf, cnt, uio))) { + if ((rv = uiomove(&hdr, cnt, uio))) { (*sc->sc_end)(sc, UIO_READ, rv); goto out; } Index: src/sys/dev/ic/tpmreg.h diff -u src/sys/dev/ic/tpmreg.h:1.5 src/sys/dev/ic/tpmreg.h:1.6 --- src/sys/dev/ic/tpmreg.h:1.5 Tue Oct 8 18:43:02 2019 +++ src/sys/dev/ic/tpmreg.h Wed Oct 9 07:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: tpmreg.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */ +/* $NetBSD: tpmreg.h,v 1.6 2019/10/09 07:30:58 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -29,6 +29,22 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define TPM_BE16(a) bswap16(a) +#define TPM_BE32(a) bswap32(a) +#else +#define TPM_BE16(a) (a) +#define TPM_BE32(a) (a) +#endif + +struct tpm_header { + uint16_t tag; + uint32_t length; + uint32_t code; +} __packed; + +/* -------------------------------------------------------------------------- */ + /* * TPM Interface Specification 1.2 (TIS12). */ Index: src/sys/dev/ic/tpmvar.h diff -u src/sys/dev/ic/tpmvar.h:1.5 src/sys/dev/ic/tpmvar.h:1.6 --- src/sys/dev/ic/tpmvar.h:1.5 Tue Oct 8 18:43:02 2019 +++ src/sys/dev/ic/tpmvar.h Wed Oct 9 07:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: tpmvar.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */ +/* $NetBSD: tpmvar.h,v 1.6 2019/10/09 07:30:58 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -69,8 +69,8 @@ struct tpm_softc { uint32_t sc_caps; }; -bool tpm12_suspend(device_t, const pmf_qual_t *); -bool tpm12_resume(device_t, const pmf_qual_t *); +bool tpm_suspend(device_t, const pmf_qual_t *); +bool tpm_resume(device_t, const pmf_qual_t *); int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t); int tpm_tis12_init(struct tpm_softc *); Index: src/sys/dev/isa/tpm_isa.c diff -u src/sys/dev/isa/tpm_isa.c:1.5 src/sys/dev/isa/tpm_isa.c:1.6 --- src/sys/dev/isa/tpm_isa.c:1.5 Tue Oct 8 18:43:03 2019 +++ src/sys/dev/isa/tpm_isa.c Wed Oct 9 07:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $ */ +/* $NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.6 2019/10/09 07:30:58 maxv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -133,6 +133,6 @@ tpm_isa_attach(device_t parent, device_t return; } - if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume)) - aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n"); + if (!pmf_device_register(self, tpm_suspend, tpm_resume)) + aprint_error_dev(self, "couldn't establish power handler\n"); }