get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2216959/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "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"
    ]
}