Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Add suspend support for TPM 2.0 chips. Check the TPM...



details:   https://anonhg.NetBSD.org/src/rev/036ea639946f
branches:  trunk
changeset: 965988:036ea639946f
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Oct 09 07:30:58 2019 +0000

description:
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.

diffstat:

 sys/dev/acpi/tpm_acpi.c |   6 ++-
 sys/dev/ic/tpm.c        |  84 ++++++++++++++++++++++++++++++++++++------------
 sys/dev/ic/tpmreg.h     |  18 +++++++++-
 sys/dev/ic/tpmvar.h     |   6 +-
 sys/dev/isa/tpm_isa.c   |   8 ++--
 5 files changed, 90 insertions(+), 32 deletions(-)

diffs (252 lines):

diff -r 9d6fd4da9bf1 -r 036ea639946f sys/dev/acpi/tpm_acpi.c
--- a/sys/dev/acpi/tpm_acpi.c   Wed Oct 09 05:59:51 2019 +0000
+++ b/sys/dev/acpi/tpm_acpi.c   Wed Oct 09 07:30:58 2019 +0000
@@ -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 @@
                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;
 
diff -r 9d6fd4da9bf1 -r 036ea639946f sys/dev/ic/tpm.c
--- a/sys/dev/ic/tpm.c  Wed Oct 09 05:59:51 2019 +0000
+++ b/sys/dev/ic/tpm.c  Wed Oct 09 07:30:58 2019 +0000
@@ -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 @@
 
 #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 @@
 
 /* -------------------------------------------------------------------------- */
 
-/*
- * Save TPM state on suspend. On resume we don't do anything, since the BIOS
- * is supposed to restore the previously saved state.
- */
-
-bool
-tpm12_suspend(device_t dev, const pmf_qual_t *qual)
+static bool
+tpm12_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[10] = {
+               0x00, 0xC1,             /* TPM_TAG_RQU_COMMAND */
+               0x00, 0x00, 0x00, 10,   /* Length in bytes */
+               0x00, 0x00, 0x00, 0x98  /* TPM_ORD_SaveState */
        };
-       uint8_t scratch[sizeof(command)];
+       struct tpm_header response;
+
+       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;
+}
 
-       (*sc->sc_write)(sc, &command, sizeof(command));
-       (*sc->sc_read)(sc, &scratch, sizeof(scratch), NULL, 0);
+static bool
+tpm20_suspend(struct tpm_softc *sc)
+{
+       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 */
+       };
+       struct tpm_header response;
+
+       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 @@
 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 @@
                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 @@
        }
 
        /* 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;
        }
diff -r 9d6fd4da9bf1 -r 036ea639946f sys/dev/ic/tpmreg.h
--- a/sys/dev/ic/tpmreg.h       Wed Oct 09 05:59:51 2019 +0000
+++ b/sys/dev/ic/tpmreg.h       Wed Oct 09 07:30:58 2019 +0000
@@ -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).
  */
diff -r 9d6fd4da9bf1 -r 036ea639946f sys/dev/ic/tpmvar.h
--- a/sys/dev/ic/tpmvar.h       Wed Oct 09 05:59:51 2019 +0000
+++ b/sys/dev/ic/tpmvar.h       Wed Oct 09 07:30:58 2019 +0000
@@ -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 @@
        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 *);
diff -r 9d6fd4da9bf1 -r 036ea639946f sys/dev/isa/tpm_isa.c
--- a/sys/dev/isa/tpm_isa.c     Wed Oct 09 05:59:51 2019 +0000
+++ b/sys/dev/isa/tpm_isa.c     Wed Oct 09 07:30:58 2019 +0000
@@ -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 @@
                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");
 }



Home | Main Index | Thread Index | Old Index