From patchwork Thu Nov 4 14:02:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Mizinski X-Patchwork-Id: 12603181 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD76BC433F5 for ; Thu, 4 Nov 2021 14:05:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B605C611EF for ; Thu, 4 Nov 2021 14:05:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231371AbhKDOIf (ORCPT ); Thu, 4 Nov 2021 10:08:35 -0400 Received: from 212.199.177.27.static.012.net.il ([212.199.177.27]:47775 "EHLO herzl.nuvoton.co.il" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S231186AbhKDOIf (ORCPT ); Thu, 4 Nov 2021 10:08:35 -0400 Received: from taln60.nuvoton.co.il (ntil-fw [212.199.177.25]) by herzl.nuvoton.co.il (8.13.8/8.13.8) with ESMTP id 1A4E24Q8029311; Thu, 4 Nov 2021 16:02:04 +0200 Received: by taln60.nuvoton.co.il (Postfix, from userid 10140) id 0773563A1E; Thu, 4 Nov 2021 16:02:16 +0200 (IST) From: amirmizi6@gmail.com To: Eyal.Cohen@nuvoton.com, jarkko@kernel.org, oshrialkoby85@gmail.com, alexander.steffen@infineon.com, robh+dt@kernel.org, mark.rutland@arm.com, peterhuewe@gmx.de, jgg@ziepe.ca, arnd@arndb.de, gregkh@linuxfoundation.org, benoit.houyere@st.com, eajames@linux.ibm.com, joel@jms.id.au Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, oshri.alkoby@nuvoton.com, tmaimon77@gmail.com, gcwilson@us.ibm.com, kgoldman@us.ibm.com, Dan.Morav@nuvoton.com, oren.tanami@nuvoton.com, shmulik.hager@nuvoton.com, amir.mizinski@nuvoton.com, Amir Mizinski Subject: [PATCH v19 1/5] tpm_tis: Fix expected bit handling Date: Thu, 4 Nov 2021 16:02:07 +0200 Message-Id: <20211104140211.6258-2-amirmizi6@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20211104140211.6258-1-amirmizi6@gmail.com> References: <20211104140211.6258-1-amirmizi6@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Amir Mizinski Currently, the driver polls the TPM_STS.stsValid field until TRUE; then it reads TPM_STS register again to verify only that TPM_STS.expect field is FALSE (i.e., it ignores TPM_STS.stsValid). Since TPM_STS.stsValid represents the TPM_STS.expect validity, a check of only one of these fields is wrong. Fix this condition so that both fields are checked in the same TPM_STS register read. Modify the signature of wait_for_tpm_stat() to tpm_tis_wait_for_stat(), adding an additional "expected" parameter to its call. tpm_tis_wait_for_stat() is now polling the TPM_STS with a mask and waits for the value in "expected". This modification adds the ability to check if certain TPM_STS bits have been cleared. For example, use the new parameter to check in status that TPM_STS_VALID is set and also that TPM_STS_EXPECT is zeroed. This prevents a racy check. Suggested-by: Benoit Houyere Signed-off-by: Amir Mizinski Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis_core.c | 61 ++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 69579ef..f833f35 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -44,9 +44,9 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, return false; } -static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, - unsigned long timeout, wait_queue_head_t *queue, - bool check_cancel) +static int tpm_tis_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 expected, + unsigned long timeout, + wait_queue_head_t *queue, bool check_cancel) { unsigned long stop; long rc; @@ -55,7 +55,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, /* check current status */ status = chip->ops->status(chip); - if ((status & mask) == mask) + if ((status & mask) == expected) return 0; stop = jiffies + timeout; @@ -83,7 +83,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX); status = chip->ops->status(chip); - if ((status & mask) == mask) + if ((status & mask) == expected) return 0; } while (time_before(jiffies, stop)); } @@ -259,10 +259,11 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) int size = 0, burstcnt, rc; while (size < count) { - rc = wait_for_tpm_stat(chip, - TPM_STS_DATA_AVAIL | TPM_STS_VALID, - chip->timeout_c, - &priv->read_queue, true); + rc = tpm_tis_wait_for_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->timeout_c, &priv->read_queue, + true); if (rc < 0) return rc; burstcnt = get_burstcount(chip); @@ -315,8 +316,9 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { + if (tpm_tis_wait_for_stat(chip, TPM_STS_VALID, TPM_STS_VALID, + chip->timeout_c, &priv->int_queue, + false) < 0) { size = -ETIME; goto out; } @@ -342,14 +344,14 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int rc, status, burstcnt; size_t count = 0; - bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; status = tpm_tis_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_ready(chip); - if (wait_for_tpm_stat - (chip, TPM_STS_COMMAND_READY, chip->timeout_b, - &priv->int_queue, false) < 0) { + if (tpm_tis_wait_for_stat(chip, TPM_STS_COMMAND_READY, + TPM_STS_COMMAND_READY, + chip->timeout_b, &priv->int_queue, + false) < 0) { rc = -ETIME; goto out_err; } @@ -369,34 +371,24 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) goto out_err; count += burstcnt; - - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { + if (tpm_tis_wait_for_stat(chip, TPM_STS_VALID | TPM_STS_DATA_EXPECT, + TPM_STS_VALID | TPM_STS_DATA_EXPECT, chip->timeout_a, + &priv->int_queue, false) < 0) { rc = -ETIME; goto out_err; } - status = tpm_tis_status(chip); - if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { - rc = -EIO; - goto out_err; - } } /* write last byte */ rc = tpm_tis_write8(priv, TPM_DATA_FIFO(priv->locality), buf[count]); if (rc < 0) goto out_err; - - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, - &priv->int_queue, false) < 0) { + if (tpm_tis_wait_for_stat(chip, TPM_STS_VALID | TPM_STS_DATA_EXPECT, + TPM_STS_VALID, chip->timeout_a, + &priv->int_queue, false) < 0) { rc = -ETIME; goto out_err; } - status = tpm_tis_status(chip); - if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { - rc = -EIO; - goto out_err; - } return 0; @@ -451,9 +443,10 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); dur = tpm_calc_ordinal_duration(chip, ordinal); - if (wait_for_tpm_stat - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, - &priv->read_queue, false) < 0) { + if (tpm_tis_wait_for_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + dur, &priv->read_queue, false) < 0) { rc = -ETIME; goto out_err; } From patchwork Thu Nov 4 14:02:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Mizinski X-Patchwork-Id: 12603171 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8FA9C433FE for ; Thu, 4 Nov 2021 14:05:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AEE54611F2 for ; Thu, 4 Nov 2021 14:05:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231152AbhKDOHw (ORCPT ); Thu, 4 Nov 2021 10:07:52 -0400 Received: from 212.199.177.27.static.012.net.il ([212.199.177.27]:47746 "EHLO herzl.nuvoton.co.il" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S230409AbhKDOHv (ORCPT ); Thu, 4 Nov 2021 10:07:51 -0400 Received: from taln60.nuvoton.co.il (ntil-fw [212.199.177.25]) by herzl.nuvoton.co.il (8.13.8/8.13.8) with ESMTP id 1A4E25Qa029312; Thu, 4 Nov 2021 16:02:05 +0200 Received: by taln60.nuvoton.co.il (Postfix, from userid 10140) id 32C8C63A1F; Thu, 4 Nov 2021 16:02:17 +0200 (IST) From: amirmizi6@gmail.com To: Eyal.Cohen@nuvoton.com, jarkko@kernel.org, oshrialkoby85@gmail.com, alexander.steffen@infineon.com, robh+dt@kernel.org, mark.rutland@arm.com, peterhuewe@gmx.de, jgg@ziepe.ca, arnd@arndb.de, gregkh@linuxfoundation.org, benoit.houyere@st.com, eajames@linux.ibm.com, joel@jms.id.au Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, oshri.alkoby@nuvoton.com, tmaimon77@gmail.com, gcwilson@us.ibm.com, kgoldman@us.ibm.com, Dan.Morav@nuvoton.com, oren.tanami@nuvoton.com, shmulik.hager@nuvoton.com, amir.mizinski@nuvoton.com, Amir Mizinski Subject: [PATCH v19 2/5] tpm: tpm_tis: Rewrite "tpm_tis_req_canceled()" Date: Thu, 4 Nov 2021 16:02:08 +0200 Message-Id: <20211104140211.6258-3-amirmizi6@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20211104140211.6258-1-amirmizi6@gmail.com> References: <20211104140211.6258-1-amirmizi6@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Amir Mizinski tpm_tis_req_canceled() function is used to check if the caller requested to abort the current operation. It was found that in some cases tpm_tis_req_canceled() wrongly returned true. Since a cancel request sets the TPM_STS.commandReady field to TRUE, the tpm_tis_req_canceled() function should check only the TPM_STS.commandReady field value. The case for TPM_VID_WINBOND is wrong and was therefore removed. Also, the default comparison is wrong. Only cmdReady bit needs to be compared instead of the full lower status register byte. Signed-off-by: Amir Mizinski --- drivers/char/tpm/tpm_tis_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index f833f35..6ff8b44 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -661,13 +661,10 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); switch (priv->manufacturer_id) { - case TPM_VID_WINBOND: - return ((status == TPM_STS_VALID) || - (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); case TPM_VID_STM: return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); default: - return (status == TPM_STS_COMMAND_READY); + return (status & TPM_STS_COMMAND_READY) == TPM_STS_COMMAND_READY; } } From patchwork Thu Nov 4 14:02:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Amir Mizinski X-Patchwork-Id: 12603177 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D8F82C433F5 for ; Thu, 4 Nov 2021 14:05:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C314160EE9 for ; Thu, 4 Nov 2021 14:05:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231379AbhKDOIA (ORCPT ); Thu, 4 Nov 2021 10:08:00 -0400 Received: from 212.199.177.27.static.012.net.il ([212.199.177.27]:47755 "EHLO herzl.nuvoton.co.il" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S231325AbhKDOH7 (ORCPT ); Thu, 4 Nov 2021 10:07:59 -0400 Received: from taln60.nuvoton.co.il (ntil-fw [212.199.177.25]) by herzl.nuvoton.co.il (8.13.8/8.13.8) with ESMTP id 1A4E26M5029313; Thu, 4 Nov 2021 16:02:06 +0200 Received: by taln60.nuvoton.co.il (Postfix, from userid 10140) id 0DD2963A20; Thu, 4 Nov 2021 16:02:18 +0200 (IST) From: amirmizi6@gmail.com To: Eyal.Cohen@nuvoton.com, jarkko@kernel.org, oshrialkoby85@gmail.com, alexander.steffen@infineon.com, robh+dt@kernel.org, mark.rutland@arm.com, peterhuewe@gmx.de, jgg@ziepe.ca, arnd@arndb.de, gregkh@linuxfoundation.org, benoit.houyere@st.com, eajames@linux.ibm.com, joel@jms.id.au Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, oshri.alkoby@nuvoton.com, tmaimon77@gmail.com, gcwilson@us.ibm.com, kgoldman@us.ibm.com, Dan.Morav@nuvoton.com, oren.tanami@nuvoton.com, shmulik.hager@nuvoton.com, amir.mizinski@nuvoton.com, Amir Mizinski Subject: [PATCH v19 3/5] tpm: tpm_tis: Verify TPM_STS register is valid after locality request Date: Thu, 4 Nov 2021 16:02:09 +0200 Message-Id: <20211104140211.6258-4-amirmizi6@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20211104140211.6258-1-amirmizi6@gmail.com> References: <20211104140211.6258-1-amirmizi6@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Amir Mizinski An invalid TPM_STS value could be used when the following two events occur: TPM does not update TPM_STS register after a locality request (TPM_STS Initial value = 0xFF), and a TPM_STS register read occurs in the tpm_tis_status(chip) function call. In probe_itpm(), a call to tpm_tis_send_data() function is made after a request_locality() call, and the condition ("if ((status & TPM_STS_COMMAND_READY) == 0)") is checked. At this moment if the status value is 0xFF, then it is considered, wrongly, in “ready” state (by checking only one bit). However, at this moment the TPM is, in fact, in "Idle" state and remains in "Idle" state because "tpm_tis_ready(chip);" was not executed. Waiting for the condition TPM_STS.tpmGo == 0, will ensure that the TPM status register has the correct value. Suggested-by: Benoit Houyere Signed-off-by: Amir Mizinski --- drivers/char/tpm/tpm_tis_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 6ff8b44..770685a 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -177,8 +177,12 @@ static int request_locality(struct tpm_chip *chip, int l) } else { /* wait for burstcount */ do { - if (check_locality(chip, l)) + if (check_locality(chip, l)) { + if (tpm_tis_wait_for_stat(chip, TPM_STS_GO, 0, chip->timeout_c, + &priv->int_queue, false) < 0) + return -ETIME; return l; + } tpm_msleep(TPM_TIMEOUT); } while (time_before(jiffies, stop)); } From patchwork Thu Nov 4 14:02:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Amir Mizinski X-Patchwork-Id: 12603179 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8644BC4332F for ; Thu, 4 Nov 2021 14:05:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 674F060ED7 for ; Thu, 4 Nov 2021 14:05:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231359AbhKDOIB (ORCPT ); Thu, 4 Nov 2021 10:08:01 -0400 Received: from 212.199.177.27.static.012.net.il ([212.199.177.27]:47756 "EHLO herzl.nuvoton.co.il" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S231332AbhKDOIA (ORCPT ); Thu, 4 Nov 2021 10:08:00 -0400 Received: from taln60.nuvoton.co.il (ntil-fw [212.199.177.25]) by herzl.nuvoton.co.il (8.13.8/8.13.8) with ESMTP id 1A4E27JY029314; Thu, 4 Nov 2021 16:02:07 +0200 Received: by taln60.nuvoton.co.il (Postfix, from userid 10140) id E8B5663A21; Thu, 4 Nov 2021 16:02:18 +0200 (IST) From: amirmizi6@gmail.com To: Eyal.Cohen@nuvoton.com, jarkko@kernel.org, oshrialkoby85@gmail.com, alexander.steffen@infineon.com, robh+dt@kernel.org, mark.rutland@arm.com, peterhuewe@gmx.de, jgg@ziepe.ca, arnd@arndb.de, gregkh@linuxfoundation.org, benoit.houyere@st.com, eajames@linux.ibm.com, joel@jms.id.au Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, oshri.alkoby@nuvoton.com, tmaimon77@gmail.com, gcwilson@us.ibm.com, kgoldman@us.ibm.com, Dan.Morav@nuvoton.com, oren.tanami@nuvoton.com, shmulik.hager@nuvoton.com, amir.mizinski@nuvoton.com, Amir Mizinski Subject: [PATCH v19 4/5] tpm: tpm_tis: Add tpm_tis_i2c driver Date: Thu, 4 Nov 2021 16:02:10 +0200 Message-Id: <20211104140211.6258-5-amirmizi6@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20211104140211.6258-1-amirmizi6@gmail.com> References: <20211104140211.6258-1-amirmizi6@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Amir Mizinski I2C support for TPM devices on the TIS interface is currently available only as a proprietary driver implementation for each TPM vendor. This patch implements the infrastructure for a TCG-compliant TPM TIS I2C driver with the functionality required to communicate with a TPM device over I2C according to the "TCG PC Client PTP Interface Specification" and "Device Driver Design Principles for TPM 2.0" References: [1] "TCG PC Client Platform TPM Profile(PTP) Interface Specification for TPM 2.0" Version 01.03 Revision 22 at: https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ [2] "TCG PC Client Device Driver Design Principles for TPM 2.0" Version 1.0 Revision 27 at: https://trustedcomputinggroup.org/resource/tcg-pc-client-device-driver-design-principles-for-tpm-2-0/ Signed-off-by: Amir Mizinski Tested-by: Eddie James Tested-by: Joel Stanley --- drivers/char/tpm/Kconfig | 12 ++ drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_tis_i2c.c | 263 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 drivers/char/tpm/tpm_tis_i2c.c diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 4308f9c..4137ded 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -86,6 +86,18 @@ config TCG_TIS_SYNQUACER To compile this driver as a module, choose M here; the module will be called tpm_tis_synquacer. +config TCG_TIS_I2C + tristate "TPM I2C Interface Specification" + depends on I2C + select CRC_CCITT + select TCG_TIS_CORE + help + If you have a TPM security chip, compliant with the TCG TPM PTP + (I2C interface) specification and connected to an I2C bus master, + say Yes and it will be accessible from within Linux. + To compile this driver as a module, choose M here; + the module will be called tpm_tis_i2c. + config TCG_TIS_I2C_CR50 tristate "TPM Interface Specification 2.0 Interface (I2C - CR50)" depends on I2C diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 66d39ea..0222b1d 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -29,6 +29,7 @@ tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o obj-$(CONFIG_TCG_TIS_I2C_CR50) += tpm_tis_i2c_cr50.o +obj-$(CONFIG_TCG_TIS_I2C) += tpm_tis_i2c.o obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c new file mode 100644 index 0000000..12984a3 --- /dev/null +++ b/drivers/char/tpm/tpm_tis_i2c.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014-2021 Nuvoton Technology corporation + * + * TPM TIS I2C Device Driver Interface for devices that implement the TPM + * I2C Interface defined by "TCG PC Client Platform TPM Profile (PTP) + * Specification version 01.05 r14" and "TCG PC Client Device Driver + * Design Principles version 1.0 r27" for TPM 2.0 at + * www.trustedcomputinggroup.org + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "tpm_tis_core.h" + +#define TPM_LOC_SEL 0x04 +#define TPM_I2C_INTERFACE_CAPABILITY 0x30 +#define TPM_I2C_DEVICE_ADDRESS 0x38 +#define TPM_DATA_CSUM_ENABLE 0x40 +#define TPM_I2C_DID_VID 0x48 +#define TPM_I2C_RID 0x4C + +struct tpm_tis_i2c_phy { + struct tpm_tis_data priv; + struct i2c_client *i2c_client; + u8 *iobuf; +}; + +static inline struct tpm_tis_i2c_phy *to_tpm_tis_i2c_phy(struct tpm_tis_data *data) +{ + return container_of(data, struct tpm_tis_i2c_phy, priv); +} + +static u8 address_to_register(u32 addr) +{ + addr &= 0xFFF; + + switch (addr) { + // adapt register addresses that have changed compared to + // older TIS versions + case TPM_ACCESS(0): + return 0x04; + case TPM_LOC_SEL: + return 0x00; + case TPM_DID_VID(0): + return 0x48; + case TPM_RID(0): + return 0x4C; + default: + return addr; + } +} + +static int tpm_tis_i2c_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) +{ + struct tpm_tis_i2c_phy *phy = to_tpm_tis_i2c_phy(data); + u8 reg = address_to_register(addr); + int ret; + int i = 0; + struct i2c_msg msgs[] = { + { + .addr = phy->i2c_client->addr, + .len = sizeof(reg), + .buf = ®, + }, + { + .addr = phy->i2c_client->addr, + .len = len, + .buf = result, + .flags = I2C_M_RD, + }, + }; + + do { + ret = i2c_transfer(phy->i2c_client->adapter, msgs, + ARRAY_SIZE(msgs)); + usleep_range(250, 300); // wait default GUARD_TIME of 250µs + + } while (ret < 0 && i++ < TPM_RETRY); + + if (ret < 0) + return ret; + + return 0; +} + +static int tpm_tis_i2c_write_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, const u8 *value) +{ + struct tpm_tis_i2c_phy *phy = to_tpm_tis_i2c_phy(data); + int ret = 0; + int i = 0; + + if (phy->iobuf) { + if (len > TPM_BUFSIZE - 1) + return -EIO; + + phy->iobuf[0] = address_to_register(addr); + memcpy(phy->iobuf + 1, value, len); + + struct i2c_msg msgs[] = { + { + .addr = phy->i2c_client->addr, + .len = len + 1, + .buf = phy->iobuf, + }, + }; + + do { + ret = i2c_transfer(phy->i2c_client->adapter, + msgs, ARRAY_SIZE(msgs)); + // wait default GUARD_TIME of 250µs + usleep_range(250, 300); + } while (ret < 0 && i++ < TPM_RETRY); + } else { + u8 reg = address_to_register(addr); + + struct i2c_msg msgs[] = { + { + .addr = phy->i2c_client->addr, + .len = sizeof(reg), + .buf = ®, + }, + { + .addr = phy->i2c_client->addr, + .len = len, + .buf = (u8 *)value, + .flags = I2C_M_NOSTART, + }, + }; + + do { + ret = i2c_transfer(phy->i2c_client->adapter, msgs, + ARRAY_SIZE(msgs)); + // wait default GUARD_TIME of 250µs + usleep_range(250, 300); + } while (ret < 0 && i++ < TPM_RETRY); + } + + if (ret < 0) + return ret; + + return 0; +} + +int tpm_tis_i2c_read16(struct tpm_tis_data *data, u32 addr, u16 *result) +{ + __le16 result_le; + int rc; + + rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), + (u8 *)&result_le); + if (!rc) + *result = le16_to_cpu(result_le); + + return rc; +} + +int tpm_tis_i2c_read32(struct tpm_tis_data *data, u32 addr, u32 *result) +{ + __le32 result_le; + int rc; + + rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), + (u8 *)&result_le); + if (!rc) + *result = le32_to_cpu(result_le); + + return rc; +} + +int tpm_tis_i2c_write32(struct tpm_tis_data *data, u32 addr, u32 value) +{ + __le32 value_le; + int rc; + + value_le = cpu_to_le32(value); + + rc = data->phy_ops->write_bytes(data, addr, sizeof(u32), + (u8 *)&value_le); + + return rc; +} + +static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); + +static const struct tpm_tis_phy_ops tpm_i2c_phy_ops = { + .read_bytes = tpm_tis_i2c_read_bytes, + .write_bytes = tpm_tis_i2c_write_bytes, + .read16 = tpm_tis_i2c_read16, + .read32 = tpm_tis_i2c_read32, + .write32 = tpm_tis_i2c_write32, +}; + +static int tpm_tis_i2c_probe(struct i2c_client *dev, const struct i2c_device_id *id) +{ + struct tpm_tis_i2c_phy *phy; + const u8 loc_init = 0; + int rc; + + phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_i2c_phy), + GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->i2c_client = dev; + + if (!i2c_check_functionality(dev->adapter, I2C_FUNC_NOSTART)) { + phy->iobuf = devm_kmalloc(&dev->dev, TPM_BUFSIZE, GFP_KERNEL); + if (!phy->iobuf) + return -ENOMEM; + } + + /*select locality 0 (the driver will access only via locality 0)*/ + rc = tpm_tis_i2c_write_bytes(&phy->priv, TPM_LOC_SEL, 1, &loc_init); + if (rc < 0) + return rc; + + return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_i2c_phy_ops, + NULL); +} + +static const struct i2c_device_id tpm_tis_i2c_id[] = { + {"tpm_tis_i2c", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_id); + +static const struct of_device_id of_tis_i2c_match[] = { + { .compatible = "nuvoton,npct75x", }, + { .compatible = "tcg,tpm-tis-i2c", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_tis_i2c_match); + +static struct i2c_driver tpm_tis_i2c_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "tpm_tis_i2c", + .pm = &tpm_tis_pm, + .of_match_table = of_match_ptr(of_tis_i2c_match), + }, + .probe = tpm_tis_i2c_probe, + .id_table = tpm_tis_i2c_id, +}; + +module_i2c_driver(tpm_tis_i2c_driver); + +MODULE_DESCRIPTION("TPM Driver"); +MODULE_LICENSE("GPL"); From patchwork Thu Nov 4 14:02:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Mizinski X-Patchwork-Id: 12603175 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17357C433F5 for ; Thu, 4 Nov 2021 14:05:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EF5B3611C1 for ; Thu, 4 Nov 2021 14:05:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231314AbhKDOH7 (ORCPT ); Thu, 4 Nov 2021 10:07:59 -0400 Received: from 212.199.177.27.static.012.net.il ([212.199.177.27]:47757 "EHLO herzl.nuvoton.co.il" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S231335AbhKDOH6 (ORCPT ); Thu, 4 Nov 2021 10:07:58 -0400 Received: from taln60.nuvoton.co.il (ntil-fw [212.199.177.25]) by herzl.nuvoton.co.il (8.13.8/8.13.8) with ESMTP id 1A4E28Lu029325; Thu, 4 Nov 2021 16:02:08 +0200 Received: by taln60.nuvoton.co.il (Postfix, from userid 10140) id A916363A22; Thu, 4 Nov 2021 16:02:19 +0200 (IST) From: amirmizi6@gmail.com To: Eyal.Cohen@nuvoton.com, jarkko@kernel.org, oshrialkoby85@gmail.com, alexander.steffen@infineon.com, robh+dt@kernel.org, mark.rutland@arm.com, peterhuewe@gmx.de, jgg@ziepe.ca, arnd@arndb.de, gregkh@linuxfoundation.org, benoit.houyere@st.com, eajames@linux.ibm.com, joel@jms.id.au Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, oshri.alkoby@nuvoton.com, tmaimon77@gmail.com, gcwilson@us.ibm.com, kgoldman@us.ibm.com, Dan.Morav@nuvoton.com, oren.tanami@nuvoton.com, shmulik.hager@nuvoton.com, amir.mizinski@nuvoton.com, Amir Mizinski , Rob Herring Subject: [PATCH v19 5/5] tpm: Add YAML schema for TPM TIS I2C options Date: Thu, 4 Nov 2021 16:02:11 +0200 Message-Id: <20211104140211.6258-6-amirmizi6@gmail.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20211104140211.6258-1-amirmizi6@gmail.com> References: <20211104140211.6258-1-amirmizi6@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org From: Amir Mizinski Add a YAML schema to support tpm tis i2c related dt-bindings for the I2c PTP based physical layer. This patch adds the documentation for corresponding device tree bindings of I2C based Physical TPM. Refer to the 'I2C Interface Definition' section in 'TCG PC Client PlatformTPMProfile(PTP) Specification' publication for specification. Signed-off-by: Amir Mizinski Reviewed-by: Rob Herring --- .../bindings/security/tpm/tpm-tis-i2c.yaml | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml diff --git a/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml b/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml new file mode 100644 index 0000000..217ba8e --- /dev/null +++ b/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/security/tpm/tpm-tis-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: I2C PTP based TPM Device Tree Bindings + +maintainers: + - Amir Mizinski + +description: + Device Tree Bindings for I2C based Trusted Platform Module(TPM). + +properties: + compatible: + items: + - enum: + # Nuvoton's Trusted Platform Module (TPM) (NPCT75x) + - nuvoton,npct75x + - const: tcg,tpm-tis-i2c + + reg: + maxItems: 1 + + interrupt: + maxItems: 1 + + crc-checksum: + $ref: /schemas/types.yaml#/definitions/flag + description: + Set this flag to enable CRC checksum. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + tpm@2e { + compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c"; + reg = <0x2e>; + crc-checksum; + }; + }; +...