Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216959/?format=api
{ "id": 2216959, "url": "http://patchwork.ozlabs.org/api/patches/2216959/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260327125318.1037146-3-padmarao.begari@amd.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260327125318.1037146-3-padmarao.begari@amd.com>", "list_archive_url": null, "date": "2026-03-27T12:52:56", "name": "[2/4] tpm: Add AMD Versal Gen 2 TPM2 driver", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "fb99f5dd7927f04c19a0c799233e62d3209186e8", "submitter": { "id": 89329, "url": "http://patchwork.ozlabs.org/api/people/89329/?format=api", "name": "Begari, Padmarao", "email": "padmarao.begari@amd.com" }, "delegate": { "id": 96103, "url": "http://patchwork.ozlabs.org/api/users/96103/?format=api", "username": "apalos", "first_name": "Ilias", "last_name": "Apalodimas", "email": "apalos@gmail.com" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260327125318.1037146-3-padmarao.begari@amd.com/mbox/", "series": [ { "id": 497763, "url": "http://patchwork.ozlabs.org/api/series/497763/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=497763", "date": "2026-03-27T12:52:54", "name": "Add TPM2 support for AMD Versal Gen 2", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/497763/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216959/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216959/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=amd.com header.i=@amd.com header.a=rsa-sha256\n header.s=selector1 header.b=t6P0pzpp;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)", "phobos.denx.de;\n dmarc=pass (p=quarantine dis=none) header.from=amd.com", "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de", "phobos.denx.de;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=amd.com header.i=@amd.com header.b=\"t6P0pzpp\";\n\tdkim-atps=neutral", "phobos.denx.de;\n dmarc=pass (p=quarantine dis=none) header.from=amd.com", "phobos.denx.de;\n spf=fail smtp.mailfrom=Padmarao.Begari@amd.com" ], "Received": [ "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fj0vY278qz1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 23:54:01 +1100 (AEDT)", "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 6C6D783FC6;\n\tFri, 27 Mar 2026 13:53:57 +0100 (CET)", "by phobos.denx.de (Postfix, from userid 109)\n id 81BA283FD9; Fri, 27 Mar 2026 13:53:56 +0100 (CET)", "from MW6PR02CU001.outbound.protection.outlook.com\n (mail-westus2azlp170120002.outbound.protection.outlook.com\n [IPv6:2a01:111:f403:c007::2])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id DAEB681E18\n for <u-boot@lists.denx.de>; Fri, 27 Mar 2026 13:53:52 +0100 (CET)", "from BYAPR05CA0084.namprd05.prod.outlook.com (2603:10b6:a03:e0::25)\n by SJ2PR12MB8011.namprd12.prod.outlook.com (2603:10b6:a03:4c8::19)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9769.11; Fri, 27 Mar\n 2026 12:53:45 +0000", "from MWH0EPF000A6734.namprd04.prod.outlook.com\n (2603:10b6:a03:e0:cafe::fe) by BYAPR05CA0084.outlook.office365.com\n (2603:10b6:a03:e0::25) with Microsoft SMTP Server (version=TLS1_3,\n cipher=TLS_AES_256_GCM_SHA384) id 15.20.9745.20 via Frontend Transport; Fri,\n 27 Mar 2026 12:53:44 +0000", "from satlexmb08.amd.com (165.204.84.17) by\n MWH0EPF000A6734.mail.protection.outlook.com (10.167.249.26) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.9745.21 via Frontend Transport; Fri, 27 Mar 2026 12:53:44 +0000", "from Satlexmb09.amd.com (10.181.42.218) by satlexmb08.amd.com\n (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Fri, 27 Mar\n 2026 07:53:43 -0500", "from satlexmb08.amd.com (10.181.42.217) by satlexmb09.amd.com\n (10.181.42.218) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Fri, 27 Mar\n 2026 05:53:42 -0700", "from xhdkummari40.xilinx.com (10.180.168.240) by satlexmb08.amd.com\n (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17 via Frontend\n Transport; Fri, 27 Mar 2026 07:53:41 -0500" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,\n DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2", "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=UAPvNr2K9F9SlMvK0zSQjdHDkXIPQZN/SPHwCIEJXr47BKWHy3ae+TKBs4YSFpm5aif9RycXzuHogHgHIld4HQSMUMHR5DlVfZSWM8QOotPlqK2Xjzz9ObbRG491eWIpxJcniivXCg+nDUBR0bEqlzYwEqHmK7TtOdaDNqhxwvSLG6CbJYvHJMtG5BB2i5dHK64BZFP+SC+hD4LXpWdg7qIcgOo/Liw3SiN66QVjvamWkCsnmE7zjp1qr30cQk8FPwalca/OMmciqqfTgp2n9VxHPbMkhb1abXGZa/o3N3uZS7SKv/e104dUL/xW1ypFFBbpD+vRWDaOhWUD+PgszQ==", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=kDt1gjAPXsoRt1O/zDHnukqAjQ6bXY5Tj3jXHQx14Jg=;\n b=Rka0QCeYzCt3fqwmJR3Zfv5NanNfw8xxi74mjCsGz4kketXmSy6kanCumGMKXsLFO1J/qRd1F5aLAyjzXsi7X74V82FKJVzjMNHvldCjMkQ1lAKtbP+TvSd3O4nXS0nufBg7ULvl1O+JbtKEXnsazepfQlJ3lCpwzEkL47u+tIaEsEIthWVcwdk1bBGUhjouMhWt5Z1g1viAMN5J9zJ6EQZGeb7LxXzf9mCpc2fOSYzsdCcZ+KR7y/3TSwk8BDFkZ6jqDsi/iM5j29I1G61WHyBC4vsbdFQqByg3QyfyArclD6QVnq29zG4kmKpADJv021vrWuBarNEQ4ZqNXkpJtg==", "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 165.204.84.17) smtp.rcpttodomain=lists.denx.de smtp.mailfrom=amd.com;\n dmarc=pass (p=quarantine sp=quarantine pct=100) action=none\n header.from=amd.com; dkim=none (message not signed); arc=none (0)", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=kDt1gjAPXsoRt1O/zDHnukqAjQ6bXY5Tj3jXHQx14Jg=;\n b=t6P0pzpp3ZeruftvxOR9Z9tPjAeldgOS4DH96V4Lh1iwQZGFEJm7NNAQ9mmzgTIhoWDuYMBKtURphGqLq8ITmQ8nt4Asr8dqBDDjU7sI0uEBnsPgn5RT+SYTm3EFxuuIAcJP7CnEt5Az/OfOI/uP4iyluBQDxkRkTMpPSzRRPVQ=", "X-MS-Exchange-Authentication-Results": "spf=pass (sender IP is 165.204.84.17)\n smtp.mailfrom=amd.com; dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=amd.com;", "Received-SPF": "Pass (protection.outlook.com: domain of amd.com designates\n 165.204.84.17 as permitted sender) receiver=protection.outlook.com;\n client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C", "From": "Padmarao Begari <padmarao.begari@amd.com>", "To": "<u-boot@lists.denx.de>, <michal.simek@amd.com>", "CC": "<git@amd.com>, <padmarao.begari@amd.com>, Tom Rini <trini@konsulko.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>", "Subject": "[PATCH 2/4] tpm: Add AMD Versal Gen 2 TPM2 driver", "Date": "Fri, 27 Mar 2026 18:22:56 +0530", "Message-ID": "<20260327125318.1037146-3-padmarao.begari@amd.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260327125318.1037146-1-padmarao.begari@amd.com>", "References": "<20260327125318.1037146-1-padmarao.begari@amd.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Content-Type": "text/plain", "X-EOPAttributedMessage": "0", "X-MS-PublicTrafficType": "Email", "X-MS-TrafficTypeDiagnostic": "MWH0EPF000A6734:EE_|SJ2PR12MB8011:EE_", "X-MS-Office365-Filtering-Correlation-Id": "42c5a775-60d7-4823-5dd4-08de8bffe165", "X-MS-Exchange-SenderADCheck": "1", "X-MS-Exchange-AntiSpam-Relay": "0", "X-Microsoft-Antispam": "BCL:0;\n ARA:13230040|36860700016|376014|82310400026|1800799024|56012099003|22082099003|18002099003;", "X-Microsoft-Antispam-Message-Info": "\n VxVxAOISNAdqqFHvuC38BXuKs6/9kGy9Udp28W/IcAIA14O0r912QbJgCJ/F1s2321O6V2XXsMv5BithP+76cKb+YrA54ZzwmobcscCauKrTf8jcay4aWIHIeVuSns8s0ibeeA5ma2t7o1cai1z6lnixlANVO6BGowufHN6E7cppottA1yfmAcdVjIYZ1ll0T8M3C5pk2Vewy4F/q8HUmab5du7zp1FUDOJW0Bno7yho88s/lJHAUNtnZ/4gd22AmTWmDXTWs5AEZu+Wc5unX5YkLjwj1KtN5oISdaQjz2LIRJokbJ/GIcA/54H4U4omv/17SrcnK/Yy07DQzHQ4gxk2DXPCJoUo38RCdK83cctUUkpOyZlmtfHyP4HHascVclVe2tJ/eJZh8ZIFyPG6dt//NDVvfkowjo0aK8JfKFNnje0WIuzp+61jTLdrGWjBwjCSixD2ZgQp0R2nLm6k2mzdai7K68RImL/lkyrJOmZj4OGX/joJKRNNH8LYjIrmR11jqkr88NOh4Bd6Z0r3W/D2DbWxiRsX84R3ADeGAzWyrL7PmLYIZni9MUDpeUFjlE/DSdn0BAD7+4xPioPHgKUGBrw9Y/6x5og8KrvJOb4+RsY97KC6dzygcwQ7wzwK/xp8QP2oz2BiBflYl1mwxJijifCWecGjzta7tuoh/YR32FiXLflAZiiBiOe7U3hVMjm1+D3nCIQvZm3j4nm9goUxwK2GQDInFIaZoR4nl9qg8eraDuAP3q0+7MMux4M62kuyIbfbzEwwKG8OIFdG5Q==", "X-Forefront-Antispam-Report": "CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:satlexmb08.amd.com; PTR:InfoDomainNonexistent; CAT:NONE;\n SFS:(13230040)(36860700016)(376014)(82310400026)(1800799024)(56012099003)(22082099003)(18002099003);\n DIR:OUT; SFP:1101;", "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1", "X-MS-Exchange-AntiSpam-MessageData-0": "\n 1srGpsoTT2vFYvL/LKsS1f6NhmK4kk3y3MPYa6qPqU0LZRI5Upfewutrclk/75qETi43WazGicjFIZSHXiga4fFqaqsQYO5jeGF9k2XoS6wyK9TQ/2t2RLu9wTceqO0RbW3jZF0f/x7XnGfbE0ul9cwLc1UOtQNSKnlm/jy0l2mnibOXa8QHh9xQrCzHJDBBTLklivcX/1J7lUZa5MZdiAJwBd0TYmE5cq52a3YYbKWb91sHZCbkCR7ZM2QuR5R8IRvpFAoJbJh8pZ2keFycHQwV+FXmRPfmZIjz60HbKF1ANHYK5l8yPZrjUhSb3mtWLG0mFi1e7R3VOV2M0juhLDqtXF6YhKJ71Ctre5+6mjNZkStOt1968ZBGa3tUfBp6Yd2q9zwjpNw7ErrVCl8gD3rnuEmS9eE6+xdMTfdNvCY2LW2Mjxcsdg1ZX9TFTEXD", "X-OriginatorOrg": "amd.com", "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "27 Mar 2026 12:53:44.6292 (UTC)", "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 42c5a775-60d7-4823-5dd4-08de8bffe165", "X-MS-Exchange-CrossTenant-Id": "3dd8961f-e488-4e60-8e11-a82d994e183d", "X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp": "\n TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17];\n Helo=[satlexmb08.amd.com]", "X-MS-Exchange-CrossTenant-AuthSource": "\n MWH0EPF000A6734.namprd04.prod.outlook.com", "X-MS-Exchange-CrossTenant-AuthAs": "Anonymous", "X-MS-Exchange-CrossTenant-FromEntityHeader": "HybridOnPrem", "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "SJ2PR12MB8011", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.39", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>", "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de", "X-Virus-Status": "Clean" }, "content": "Add tpm2_versal2_smc, a TPM2 driver for AMD Versal Gen 2 that\nexposes the PLM XilOCP HW PCR service as a standard TPM2 interface.\n\nPCR operations are routed through TF-A:\n U-Boot -> xilinx_pm_request() -> SMC PASS_THROUGH -> TF-A -> IPI -> PLM\n\nPCR mapping: TPM PCR 0..7 -> PLM HW PCR 0..7\n\nSupported TPM2 commands:\n - TPM2_CC_STARTUP (no-op; PLM PCR module is always ready)\n - TPM2_CC_SELF_TEST (no-op)\n - TPM2_CC_GET_CAPABILITY (CAP_PCRS and CAP_TPM_PROPERTIES)\n - TPM2_CC_PCR_EXTEND (SHA-256 and SHA-384)\n - TPM2_CC_PCR_READ (SHA-256 and SHA-384)\n\nTwo PCR banks (SHA-256 and SHA-384) share the same 8 PLM HW PCRs.\nSHA-256 digests are zero-padded to 48 bytes (PLM native width) before\nbeing passed to PLM.\n\nSigned-off-by: Padmarao Begari <padmarao.begari@amd.com>\n---\n MAINTAINERS | 5 +\n drivers/tpm/Kconfig | 21 ++\n drivers/tpm/Makefile | 1 +\n drivers/tpm/tpm2_versal2_smc.c | 666 +++++++++++++++++++++++++++++++++\n 4 files changed, 693 insertions(+)\n create mode 100644 drivers/tpm/tpm2_versal2_smc.c", "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex d4b527560aa..14b57772d71 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1841,6 +1841,11 @@ F:\tdrivers/tpm/\n F:\tinclude/tpm*\n F:\tlib/tpm*\n \n+TPM2 AMD VERSAL GEN 2 DRIVER\n+M:\tPadmarao Begari <padmarao.begari@amd.com>\n+S:\tMaintained\n+F:\tdrivers/tpm/tpm2_versal2_smc.c\n+\n TQ GROUP\n #M:\tMartin Krause <martin.krause@tq-systems.de>\n S:\tOrphaned (Since 2016-02)\ndiff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig\nindex 219ea606b50..6f54ae5609e 100644\n--- a/drivers/tpm/Kconfig\n+++ b/drivers/tpm/Kconfig\n@@ -200,6 +200,27 @@ config TPM2_EVENT_LOG_SIZE\n \t allocated twice. One for the eventlog it self and one for the\n \t configuration table that is required from the TCG2 spec\n \n+config TPM2_VERSAL2_SMC\n+\tbool \"AMD Versal Gen 2 TPM2 driver (via TF-A SMC)\"\n+\tdepends on TPM_V2 && ZYNQMP_FIRMWARE && ARCH_VERSAL2\n+\tselect SHA384\n+\thelp\n+\t Enable the AMD Versal Gen 2 TPM2 driver. Exposes the PLM XilOCP\n+\t PCR service as a standard TPM2 interface.\n+\n+\t All PCR operations are routed through xilinx_pm_request(), which\n+\t issues an ARM SMC using the Versal Gen 2 extended calling convention.\n+\t TF-A passes the call through to the PLM XilOCP module (module ID 13)\n+\t over IPI.\n+\n+\t PCR mapping:\n+\t TPM PCR 0..7 -> HW PCR 0..7 (XOCP_API_EXTEND_HWPCR)\n+\n+\t Supported TPM2 commands: STARTUP, SELF_TEST, GET_CAPABILITY,\n+\t PCR_EXTEND, PCR_READ.\n+\n+\t If unsure, say N.\n+\n endif # TPM_V2\n \n endmenu\ndiff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile\nindex b83ce703ec0..7ef5bcf6be1 100644\n--- a/drivers/tpm/Makefile\n+++ b/drivers/tpm/Makefile\n@@ -14,3 +14,4 @@ obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_core.o tpm2_tis_spi.o\n obj-$(CONFIG_TPM2_TIS_I2C) += tpm2_tis_core.o tpm2_tis_i2c.o\n obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o\n obj-$(CONFIG_TPM2_MMIO) += tpm2_tis_core.o tpm2_tis_mmio.o\n+obj-$(CONFIG_TPM2_VERSAL2_SMC) += tpm2_versal2_smc.o\ndiff --git a/drivers/tpm/tpm2_versal2_smc.c b/drivers/tpm/tpm2_versal2_smc.c\nnew file mode 100644\nindex 00000000000..266d3bde45a\n--- /dev/null\n+++ b/drivers/tpm/tpm2_versal2_smc.c\n@@ -0,0 +1,666 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Copyright (C) 2026, Advanced Micro Devices, Inc.\n+ *\n+ * Author:\n+ * Padmarao Begari <padmarao.begari@amd.com>\n+ *\n+ * Description:\n+ * AMD Versal Gen 2 TPM2 driver via TF-A SMC.\n+ *\n+ * Exposes PLM XilOCP PCR services as a U-Boot DM TPM (UCLASS_TPM) device.\n+ * All calls go through zynqmp_pm_xilocp_extend_hwpcr() /\n+ * zynqmp_pm_xilocp_get_hwpcr() (firmware-zynqmp.c) which call\n+ * xilinx_pm_request() -> smc_call_enhanced() -> ARM SMC (PASS_THROUGH) ->\n+ * TF-A -> IPI -> PLM XilOCP (module ID 13).\n+ *\n+ * Communication path:\n+ * U-Boot -> zynqmp_pm_xilocp_*() -> xilinx_pm_request()\n+ * -> SMC (PASS_THROUGH) -> TF-A -> IPI -> PLM\n+ *\n+ * PCR mapping (U-Boot TPM PCR index -> XilOCP PLM PCR):\n+ * 0..7 -> HW PCR 0..7 (extend: XOCP_API_EXTEND_HWPCR,\n+ * read: XOCP_API_GET_HWPCR)\n+ *\n+ * Both SHA-256 and SHA-384 banks map to the same 8 HW PCRs. SHA-256 digests\n+ * are zero-padded to 48 bytes before passing to PLM (SHA3-384 native width).\n+ *\n+ * Supported TPM2 commands:\n+ * TPM2_CC_STARTUP (0x0144) - no-op, always succeeds\n+ * TPM2_CC_SELF_TEST (0x0143) - no-op, always succeeds\n+ * TPM2_CC_GET_CAPABILITY (0x017a) - reports PCR banks and TPM properties\n+ * TPM2_CC_PCR_EXTEND (0x0182) - extend HW PCR via PLM\n+ * TPM2_CC_PCR_READ (0x017e) - read HW PCR via PLM\n+ *\n+ * No device tree node is required. The driver is automatically bound as\n+ * a child of the zynqmp_firmware device by zynqmp_firmware_bind() after\n+ * confirming that PLM supports XOCP_API_EXTEND_HWPCR and XOCP_API_GET_HWPCR.\n+ */\n+\n+#define LOG_CATEGORY UCLASS_TPM\n+\n+#include <cpu_func.h>\n+#include <dm.h>\n+#include <log.h>\n+#include <tpm-common.h>\n+#include <tpm-v2.h>\n+#include <zynqmp_firmware.h>\n+\n+#include <asm/cache.h>\n+#include <dm/device_compat.h>\n+#include <linux/bitops.h>\n+#include <linux/string.h>\n+#include <linux/unaligned/be_byteshift.h>\n+\n+/* PCR count and hash size (SHA3-384) */\n+#define HW_PCR_COUNT\t8U\n+#define PCR_HASH_SIZE\tTPM2_SHA384_DIGEST_SIZE\n+\n+/* Common TPM2 response header: tag(2) + size(4) + rc(4) = 10 bytes */\n+struct tpm2_resp_hdr {\n+\t__be16 tag;\n+\t__be32 size;\n+\t__be32 rc;\n+} __packed;\n+\n+/* One PCR bank descriptor in a GetCapability(CAP_PCRS) response */\n+struct tpm2_pcr_bank_desc {\n+\t__be16 hash_alg;\n+\tu8 size_of_select;\n+\tu8 pcr_select;\n+} __packed;\n+\n+/* Full GetCapability(CAP_PCRS) response */\n+struct tpm2_resp_cap_pcrs {\n+\tstruct tpm2_resp_hdr hdr;\n+\tu8 more_data;\n+\t__be32 capability;\n+\t__be32 count;\n+\tstruct tpm2_pcr_bank_desc banks[2];\n+} __packed;\n+\n+/* PCR_Read response (digest payload follows the fixed header) */\n+struct tpm2_resp_pcr_read {\n+\tstruct tpm2_resp_hdr hdr;\n+\t__be32 update_count;\n+\tu8 digest[];\n+} __packed;\n+\n+/* One property entry in a GetCapability(CAP_TPM_PROPERTIES) response */\n+struct tpm2_tagged_prop {\n+\t__be32 property;\n+\t__be32 value;\n+} __packed;\n+\n+/* Fixed header of a GetCapability(CAP_TPM_PROPERTIES) response */\n+struct tpm2_resp_cap_props {\n+\tstruct tpm2_resp_hdr hdr;\n+\tu8 more_data;\n+\t__be32 capability;\n+\t__be32 count;\n+\tstruct tpm2_tagged_prop props[];\n+} __packed;\n+\n+/* Common TPM2 command header: tag(2) + size(4) + cc(4) = 10 bytes */\n+struct tpm2_req_hdr {\n+\t__be16 tag;\n+\t__be32 size;\n+\t__be32 cc;\n+} __packed;\n+\n+/* GET_CAPABILITY command */\n+struct tpm2_cmd_get_capability {\n+\tstruct tpm2_req_hdr hdr;\n+\t__be32 capability;\n+\t__be32 property;\n+\t__be32 property_count;\n+} __packed;\n+\n+/*\n+ * PCR_EXTEND command fixed prefix.\n+ * A variable-length auth area of auth_size bytes follows at offset\n+ * sizeof(*c), then __be32 digest_count, __be16 hash_alg, u8 digest[].\n+ */\n+struct tpm2_cmd_pcr_extend {\n+\tstruct tpm2_req_hdr hdr;\n+\t__be32 pcr_handle;\n+\t__be32 auth_size;\n+} __packed;\n+\n+/* PCR_READ command */\n+struct tpm2_cmd_pcr_read {\n+\tstruct tpm2_req_hdr hdr;\n+\t__be32 sel_count;\n+\t__be16 hash_alg;\n+\tu8 size_of_select;\n+\tu8 pcr_select[];\n+} __packed;\n+\n+struct tpm2_versal2_priv {\n+\tu8 *pcr_buf;\n+};\n+\n+/**\n+ * hw_pcr_extend() - Extend a Hardware PCR with a 48-byte hash.\n+ * @pcr_buf: DMA buffer holding the digest (cache-flushed before PLM DMA read)\n+ * @pcr_num: HW PCR index (0..HW_PCR_COUNT-1)\n+ *\n+ * Return: 0 on success, PLM error code on failure.\n+ */\n+static int hw_pcr_extend(u8 *pcr_buf, u32 pcr_num)\n+{\n+\tulong hash_addr = (ulong)pcr_buf;\n+\n+\tflush_dcache_range(hash_addr, hash_addr + PCR_HASH_SIZE);\n+\n+\treturn zynqmp_pm_xilocp_extend_hwpcr(pcr_num, hash_addr, PCR_HASH_SIZE);\n+}\n+\n+/**\n+ * hw_pcr_get() - Read a Hardware PCR value into pcr_buf.\n+ * @pcr_buf: DMA buffer for PLM to write the result into\n+ * @pcr_mask: Bitmask of PCRs to read; bit N selects HW PCR N\n+ *\n+ * Cache handling (DMA receive pattern):\n+ * 1. Invalidate BEFORE: discard dirty CPU cache lines so they cannot be\n+ * written back after PLM's DMA write, corrupting PLM's data.\n+ * 2. PLM DMA writes PCR value(s) to physical memory.\n+ * 3. Invalidate AFTER: discard stale CPU cache so the CPU reads PLM's\n+ * freshly written data from physical memory.\n+ *\n+ * Return: 0 on success, PLM error code on failure.\n+ */\n+static int hw_pcr_get(u8 *pcr_buf, u32 pcr_mask)\n+{\n+\tulong buf_addr = (ulong)pcr_buf;\n+\tint ret;\n+\n+\tinvalidate_dcache_range(buf_addr, buf_addr + PCR_HASH_SIZE);\n+\n+\tret = zynqmp_pm_xilocp_get_hwpcr(pcr_mask, buf_addr, PCR_HASH_SIZE);\n+\tif (!ret)\n+\t\tinvalidate_dcache_range(buf_addr, buf_addr + PCR_HASH_SIZE);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * build_simple_response() - Build a minimal 10-byte TPM2 response.\n+ * @resp: Output buffer (must be >= TPM_HEADER_SIZE bytes)\n+ * @rc: TPM2 response code (e.g. TPM2_RC_SUCCESS)\n+ *\n+ * Return: the response size (TPM_HEADER_SIZE).\n+ */\n+static size_t build_simple_response(u8 *resp, u32 rc)\n+{\n+\tstruct tpm2_resp_hdr *r = (struct tpm2_resp_hdr *)resp;\n+\n+\tr->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);\n+\tr->size = cpu_to_be32(sizeof(*r));\n+\tr->rc = cpu_to_be32(rc);\n+\n+\treturn sizeof(*r);\n+}\n+\n+/**\n+ * build_pcr_read_response() - Build a TPM2 PCR_Read response.\n+ * @resp: Output buffer (must be >= 14 + digest_len bytes)\n+ * @pcr_data: 48-byte PCR value from PLM\n+ * @digest_len: Number of bytes to include from pcr_data (32 for SHA256,\n+ * 48 for SHA384)\n+ *\n+ * PLM stores SHA3-384 (48 bytes) internally. We return the first\n+ * digest_len bytes of that value to match the algorithm the caller\n+ * requested:\n+ * SHA256 -> digest_len = 32 -> response is 46 bytes\n+ * SHA384 -> digest_len = 48 -> response is 62 bytes\n+ *\n+ * The caller (tpm2_pcr_read) extracts the digest as:\n+ * digest = response + (response_len - digest_len) = response + 14\n+ *\n+ * Return: the response size (14 + digest_len).\n+ */\n+static size_t build_pcr_read_response(u8 *resp, const u8 *pcr_data,\n+\t\t\t\t u32 digest_len)\n+{\n+\tstruct tpm2_resp_pcr_read *r = (struct tpm2_resp_pcr_read *)resp;\n+\tsize_t total = sizeof(*r) + digest_len;\n+\n+\tr->hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);\n+\tr->hdr.size = cpu_to_be32((u32)total);\n+\tr->hdr.rc = cpu_to_be32(TPM2_RC_SUCCESS);\n+\tr->update_count = cpu_to_be32(0);\n+\tmemcpy(r->digest, pcr_data, digest_len);\n+\n+\treturn total;\n+}\n+\n+/**\n+ * build_cap_pcrs_response() - Build a TPM2 GetCapability(CAP_PCRS) response.\n+ * @resp: Output buffer (must be >= 27 bytes)\n+ *\n+ * Reports two PCR banks - SHA256 and SHA384 - each with 8 PCRs\n+ * (indices 0-7, 1-byte pcrSelect bitmap, 0xff).\n+ *\n+ * Both banks are backed by PLM HW PCR 0-7. They share the same\n+ * underlying 48-byte PCR value; the algorithm only controls how many\n+ * bytes are returned on a read (32 for SHA256, 48 for SHA384) and how\n+ * the incoming digest is formatted on extend (zero-padded to 48 for\n+ * SHA256, passed directly for SHA384).\n+ *\n+ * CONFIG_SHA384=y is required so that tpm2_algorithm_supported(SHA384)\n+ * returns true and tpm2_check_active_banks() passes for pcr_extend.\n+ *\n+ * Response layout (27 bytes):\n+ * [0..1] tag = TPM2_ST_NO_SESSIONS\n+ * [2..5] size = 27\n+ * [6..9] rc = TPM2_RC_SUCCESS\n+ * [10] moreData = 0\n+ * [11..14] capability = TPM2_CAP_PCRS\n+ * [15..18] count = 2\n+ * [19..20] hash[0] = TPM2_ALG_SHA256 (0x000b)\n+ * [21] sizeofSelect = 1 (1 byte covers PCRs 0-7)\n+ * [22] pcrSelect[0] = 0xff\n+ * [23..24] hash[1] = TPM2_ALG_SHA384 (0x000c)\n+ * [25] sizeofSelect = 1\n+ * [26] pcrSelect[1] = 0xff\n+ *\n+ * Return: the response size (27).\n+ */\n+static size_t build_cap_pcrs_response(u8 *resp)\n+{\n+\tstruct tpm2_resp_cap_pcrs *r = (struct tpm2_resp_cap_pcrs *)resp;\n+\n+\tr->hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);\n+\tr->hdr.size = cpu_to_be32(sizeof(*r));\n+\tr->hdr.rc = cpu_to_be32(TPM2_RC_SUCCESS);\n+\tr->more_data = 0;\n+\tr->capability = cpu_to_be32(TPM2_CAP_PCRS);\n+\tr->count = cpu_to_be32(ARRAY_SIZE(r->banks));\n+\t/* bank 0: SHA256 */\n+\tr->banks[0].hash_alg = cpu_to_be16(TPM2_ALG_SHA256);\n+\tr->banks[0].size_of_select = 1; /* 1 byte covers PCRs 0-7 */\n+\tr->banks[0].pcr_select = 0xff; /* PCRs 0-7 active */\n+\t/* bank 1: SHA384 */\n+\tr->banks[1].hash_alg = cpu_to_be16(TPM2_ALG_SHA384);\n+\tr->banks[1].size_of_select = 1;\n+\tr->banks[1].pcr_select = 0xff;\n+\n+\treturn sizeof(*r);\n+}\n+\n+/**\n+ * tpm_props - Minimal TPM2 fixed-property table (TPM2_CAP_TPM_PROPERTIES).\n+ *\n+ * Covers the properties most commonly queried by U-Boot and host software.\n+ * The table is searched linearly; entries need not be sorted.\n+ */\n+static const struct {\n+\tu32 prop;\n+\tu32 val;\n+} tpm_props[] = {\n+\t{ TPM2_PT_MANUFACTURER, ('A' << 24) | ('M' << 16) | ('D' << 8) | ' ' },\n+\t{ TPM2_PT_PCR_COUNT, HW_PCR_COUNT },\n+\t{ TPM2_PT_MAX_COMMAND_SIZE, TPM_MAX_BUF_SIZE },\n+\t{ TPM2_PT_MAX_RESPONSE_SIZE, TPM_MAX_BUF_SIZE },\n+};\n+\n+/**\n+ * build_cap_tpm_props_response() - Build a GetCapability(CAP_TPM_PROPERTIES)\n+ * response for any property range.\n+ * @resp: Output buffer of @buf_size bytes\n+ * @buf_size: Size of @resp in bytes; prop_count is clamped to fit\n+ * @prop_start: First property ID requested (inclusive)\n+ * @prop_count: Number of consecutive property IDs requested\n+ *\n+ * Always returns exactly prop_count entries (after clamping to buf_size) so\n+ * the U-Boot tpm2_get_capability() caller reads the correct number of\n+ * properties from the buffer. Properties not found in tpm_props[] are\n+ * returned with value 0.\n+ *\n+ * Return: the response size.\n+ */\n+static size_t build_cap_tpm_props_response(u8 *resp, size_t buf_size,\n+\t\t\t\t\t u32 prop_start, u32 prop_count)\n+{\n+\tstruct tpm2_resp_cap_props *r = (struct tpm2_resp_cap_props *)resp;\n+\tu32 max_count;\n+\tsize_t total;\n+\tsize_t j;\n+\tu32 n;\n+\n+\tif (buf_size < sizeof(*r))\n+\t\treturn build_simple_response(resp, TPM2_RC_SIZE);\n+\n+\tmax_count = (u32)((buf_size - sizeof(*r)) / sizeof(r->props[0]));\n+\tif (prop_count > max_count)\n+\t\tprop_count = max_count;\n+\n+\ttotal = sizeof(*r) + prop_count * sizeof(r->props[0]);\n+\n+\tr->hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);\n+\tr->hdr.size = cpu_to_be32((u32)total);\n+\tr->hdr.rc = cpu_to_be32(TPM2_RC_SUCCESS);\n+\tr->more_data = 0;\n+\tr->capability = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);\n+\tr->count = cpu_to_be32(prop_count);\n+\n+\t/*\n+\t * Always return exactly prop_count entries so the U-Boot\n+\t * tpm2_get_capability() caller reads the correct number of entries\n+\t * from the buffer. Properties not in our table are returned as 0.\n+\t */\n+\tfor (n = 0; n < prop_count; n++) {\n+\t\tu32 pid = prop_start + n;\n+\t\tu32 val = 0;\n+\n+\t\tfor (j = 0; j < ARRAY_SIZE(tpm_props); j++) {\n+\t\t\tif (tpm_props[j].prop == pid) {\n+\t\t\t\tval = tpm_props[j].val;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tr->props[n].property = cpu_to_be32(pid);\n+\t\tr->props[n].value = cpu_to_be32(val);\n+\t}\n+\n+\treturn total;\n+}\n+\n+/**\n+ * tpm2_versal2_smc_xfer() - Translate TPM2 command bytes to PLM SMC calls.\n+ * @dev: TPM device\n+ * @sendbuf: Raw TPM2 command buffer\n+ * @send_size: Length of @sendbuf in bytes\n+ * @recvbuf: Output buffer for the TPM2 response\n+ * @recv_len: On return, the number of bytes written to @recvbuf\n+ *\n+ * Implements struct tpm_ops.xfer. Receives a raw TPM2 command buffer,\n+ * dispatches to the appropriate PLM function, and writes a TPM2-formatted\n+ * response.\n+ *\n+ * Return: 0 on success, negative error code on failure.\n+ */\n+static int tpm2_versal2_smc_xfer(struct udevice *dev, const u8 *sendbuf,\n+\t\t\t\t size_t send_size, u8 *recvbuf,\n+\t\t\t\t size_t *recv_len)\n+{\n+\tconst struct tpm2_req_hdr *hdr = (const struct tpm2_req_hdr *)sendbuf;\n+\tsize_t resp_len = build_simple_response(recvbuf, TPM2_RC_FAILURE);\n+\tstruct tpm2_versal2_priv *priv = dev_get_priv(dev);\n+\tu8 *pcr_buf = priv->pcr_buf;\n+\tu32 cc;\n+\n+\tif (send_size < sizeof(*hdr)) {\n+\t\tlog_debug(\"command too short (%zu bytes)\\n\", send_size);\n+\t\t*recv_len = build_simple_response(recvbuf, TPM2_RC_SIZE);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcc = be32_to_cpu(hdr->cc);\n+\n+\tswitch (cc) {\n+\tcase TPM2_CC_STARTUP:\n+\tcase TPM2_CC_SELF_TEST:\n+\t\t/* PLM PCR module is always ready; no initialization needed. */\n+\t\tresp_len = build_simple_response(recvbuf, TPM2_RC_SUCCESS);\n+\t\tbreak;\n+\n+\tcase TPM2_CC_GET_CAPABILITY: {\n+\t\tconst struct tpm2_cmd_get_capability *c =\n+\t\t\t(const struct tpm2_cmd_get_capability *)sendbuf;\n+\t\tu32 cap, prop, prop_count;\n+\n+\t\tif (send_size < sizeof(*c)) {\n+\t\t\tresp_len = build_simple_response(recvbuf, TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tcap = be32_to_cpu(c->capability);\n+\t\tprop = be32_to_cpu(c->property);\n+\t\tprop_count = be32_to_cpu(c->property_count);\n+\n+\t\tif (cap == TPM2_CAP_PCRS) {\n+\t\t\tresp_len = build_cap_pcrs_response(recvbuf);\n+\t\t} else if (cap == TPM2_CAP_TPM_PROPERTIES) {\n+\t\t\tresp_len = build_cap_tpm_props_response(recvbuf,\n+\t\t\t\t\t\t\t\tTPM_MAX_BUF_SIZE,\n+\t\t\t\t\t\t\t\tprop,\n+\t\t\t\t\t\t\t\tprop_count);\n+\t\t} else {\n+\t\t\tlog_debug(\"unsupported cap=0x%08x\\n\", cap);\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n+\tcase TPM2_CC_PCR_EXTEND: {\n+\t\tconst struct tpm2_cmd_pcr_extend *c =\n+\t\t\t(const struct tpm2_cmd_pcr_extend *)sendbuf;\n+\t\tu32 pcr_handle, auth_size, digest_len = 0;\n+\t\tconst u8 *digest;\n+\t\tu16 hash_alg;\n+\n+\t\tif (send_size < sizeof(*c)) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tpcr_handle = be32_to_cpu(c->pcr_handle);\n+\t\tauth_size = be32_to_cpu(c->auth_size);\n+\n+\t\t/* Need auth area + digest_count(4) + hash_alg(2) */\n+\t\tif (send_size < sizeof(*c) + auth_size +\n+\t\t\t\tsizeof(__be32) + sizeof(__be16)) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\thash_alg = get_unaligned_be16(sendbuf + sizeof(*c) +\n+\t\t\t\t\t auth_size + sizeof(__be32));\n+\n+\t\tswitch (hash_alg) {\n+\t\tcase TPM2_ALG_SHA384:\n+\t\t\tdigest_len = PCR_HASH_SIZE;\n+\t\t\tbreak;\n+\t\tcase TPM2_ALG_SHA256:\n+\t\t\tdigest_len = TPM2_SHA256_DIGEST_SIZE;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!digest_len)\n+\t\t\tbreak;\n+\n+\t\tif (send_size < sizeof(*c) + auth_size +\n+\t\t\t\tsizeof(__be32) + sizeof(__be16) + digest_len) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (pcr_handle >= HW_PCR_COUNT) {\n+\t\t\tlog_debug(\"PCR index %u out of range\\n\", pcr_handle);\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tdigest = sendbuf + sizeof(*c) + auth_size +\n+\t\t\t sizeof(__be32) + sizeof(__be16);\n+\n+\t\t/*\n+\t\t * Copy digest into priv buffer, zero-padding to 48 bytes.\n+\t\t * Both SHA256 and SHA384 extend the same HW PCR; SHA256\n+\t\t * digests are zero-padded to 48 bytes, SHA384 used as-is.\n+\t\t */\n+\t\tmemset(pcr_buf, 0, PCR_HASH_SIZE);\n+\t\tmemcpy(pcr_buf, digest, digest_len);\n+\n+\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t hw_pcr_extend(pcr_buf, pcr_handle)\n+\t\t\t\t\t\t ? TPM2_RC_FAILURE\n+\t\t\t\t\t\t : TPM2_RC_SUCCESS);\n+\t\tbreak;\n+\t}\n+\n+\tcase TPM2_CC_PCR_READ: {\n+\t\tconst struct tpm2_cmd_pcr_read *c =\n+\t\t\t(const struct tpm2_cmd_pcr_read *)sendbuf;\n+\t\tu32 pcr_handle, pcr_mask, digest_len = 0;\n+\t\tbool found = false;\n+\t\tconst u8 *sel;\n+\t\tu8 sel_sz;\n+\t\tint i;\n+\n+\t\tif (send_size < sizeof(*c)) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* Only one PCR selection block is supported */\n+\t\tif (be32_to_cpu(c->sel_count) != 1) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tsel_sz = c->size_of_select;\n+\n+\t\tif (send_size < sizeof(*c) + sel_sz) {\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_SIZE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tsel = c->pcr_select;\n+\n+\t\tswitch (be16_to_cpu(c->hash_alg)) {\n+\t\tcase TPM2_ALG_SHA384:\n+\t\t\tdigest_len = PCR_HASH_SIZE;\n+\t\t\tbreak;\n+\t\tcase TPM2_ALG_SHA256:\n+\t\t\tdigest_len = TPM2_SHA256_DIGEST_SIZE;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (!digest_len)\n+\t\t\tbreak;\n+\n+\t\t/* Find the first set PCR bit in the selection bitmap */\n+\t\tfor (i = 0; i < (int)sel_sz * 8; i++) {\n+\t\t\tif (sel[i / 8] & BIT(i % 8)) {\n+\t\t\t\tpcr_handle = (u32)i;\n+\t\t\t\tfound = true;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!found) {\n+\t\t\tlog_debug(\"PCR_READ: no PCR selected\\n\");\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (pcr_handle >= HW_PCR_COUNT) {\n+\t\t\tlog_debug(\"PCR index %u out of range\\n\", pcr_handle);\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_VALUE);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tpcr_mask = BIT(pcr_handle);\n+\n+\t\t/*\n+\t\t * Both SHA256 and SHA384 read the same HW PCR.\n+\t\t * digest_len controls how many bytes of the 48-byte PLM\n+\t\t * value are returned (32 for SHA256, 48 for SHA384).\n+\t\t */\n+\t\tif (hw_pcr_get(pcr_buf, pcr_mask))\n+\t\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t\t TPM2_RC_FAILURE);\n+\t\telse\n+\t\t\tresp_len = build_pcr_read_response(recvbuf, pcr_buf,\n+\t\t\t\t\t\t\t digest_len);\n+\t\tbreak;\n+\t}\n+\n+\tdefault:\n+\t\tlog_debug(\"unsupported command code 0x%08x\\n\", cc);\n+\t\tresp_len = build_simple_response(recvbuf,\n+\t\t\t\t\t\t TPM2_RC_COMMAND_CODE);\n+\t\tbreak;\n+\t}\n+\n+\t*recv_len = resp_len;\n+\n+\treturn 0;\n+}\n+\n+static int tpm2_versal2_smc_open(struct udevice *dev)\n+{\n+\treturn 0;\n+}\n+\n+static int tpm2_versal2_smc_close(struct udevice *dev)\n+{\n+\treturn 0;\n+}\n+\n+static int tpm2_versal2_smc_get_desc(struct udevice *dev, char *buf, int size)\n+{\n+\treturn snprintf(buf, size, \"AMD Versal Gen 2 TPM2 (via TF-A SMC)\");\n+}\n+\n+static int tpm2_versal2_smc_probe(struct udevice *dev)\n+{\n+\tstruct tpm_chip_priv *tpm_priv = dev_get_uclass_priv(dev);\n+\tstruct tpm2_versal2_priv *priv = dev_get_priv(dev);\n+\n+\tpriv->pcr_buf = memalign(ARCH_DMA_MINALIGN, PCR_HASH_SIZE);\n+\tif (!priv->pcr_buf)\n+\t\treturn -ENOMEM;\n+\n+\ttpm_priv->version = TPM_V2;\n+\ttpm_priv->pcr_count = HW_PCR_COUNT;\n+\ttpm_priv->pcr_select_min = 1;\n+\n+\treturn 0;\n+}\n+\n+static int tpm2_versal2_smc_remove(struct udevice *dev)\n+{\n+\tstruct tpm2_versal2_priv *priv = dev_get_priv(dev);\n+\n+\tfree(priv->pcr_buf);\n+\n+\treturn 0;\n+}\n+\n+static const struct tpm_ops tpm2_versal2_smc_ops = {\n+\t.open = tpm2_versal2_smc_open,\n+\t.close = tpm2_versal2_smc_close,\n+\t.get_desc = tpm2_versal2_smc_get_desc,\n+\t.xfer = tpm2_versal2_smc_xfer,\n+};\n+\n+U_BOOT_DRIVER(tpm2_versal2_smc) = {\n+\t.name = \"tpm2_versal2_smc\",\n+\t.id = UCLASS_TPM,\n+\t.ops = &tpm2_versal2_smc_ops,\n+\t.probe = tpm2_versal2_smc_probe,\n+\t.remove = tpm2_versal2_smc_remove,\n+\t.priv_auto = sizeof(struct tpm2_versal2_priv),\n+};\n", "prefixes": [ "2/4" ] }