[PATCH 1/4] firmware: zynqmp: Add HW PCR API for Versal Gen 2

Padmarao Begari padmarao.begari at amd.com
Fri Mar 27 13:52:55 CET 2026


Add three helper functions for PLM XilOCP PCR operations on AMD
Versal Gen 2, all routed via the existing xilinx_pm_request()
SMC PASS_THROUGH path:

  - zynqmp_pm_xilocp_is_feature_supported(): queries PLM for API
    availability using XOCP_API_FEATURES (fn 0)
  - zynqmp_pm_xilocp_extend_hwpcr(): extends a HW PCR with a 48-byte
    digest using XOCP_API_EXTEND_HWPCR (fn 1)
  - zynqmp_pm_xilocp_get_hwpcr(): reads HW PCR value(s) into a
    caller-supplied buffer using XOCP_API_GET_HWPCR (fn 2)

Also define the PLM_IPI_HDR() macro and XilOCP API ID constants in
zynqmp_firmware.h. PLM_IPI_HDR() takes an explicit module_id
parameter to encode the PLM module ID and function ID into the IPI
payload header word passed to xilinx_pm_request(), making it reusable
for other PLM modules.

The new functions are added into the existing CONFIG_ARCH_VERSAL2
guard block.

Signed-off-by: Padmarao Begari <padmarao.begari at amd.com>
---
 drivers/firmware/firmware-zynqmp.c | 72 +++++++++++++++++++++++++++++-
 include/zynqmp_firmware.h          | 24 ++++++++++
 2 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index f8a9945c1da..2315d5932d1 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -3,7 +3,7 @@
  * Xilinx Zynq MPSoC Firmware driver
  *
  * Copyright (C) 2018-2019 Xilinx, Inc.
- * Copyright (C) 2022 - 2025, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc.
  */
 
 #include <asm/arch/hardware.h>
@@ -197,6 +197,76 @@ int zynqmp_pm_ufs_cal_reg(u32 *value)
 	*value = readl(PMXC_EFUSE_CACHE_BASE_ADDRESS + PMXC_UFS_CAL_1_OFFSET);
 	return 0;
 }
+
+/**
+ * zynqmp_pm_xilocp_is_feature_supported() - Query PLM XilOCP for API support.
+ * @api_id: XilOCP API function ID to check (e.g. XOCP_API_EXTEND_HWPCR)
+ *
+ * Sends XOCP_API_FEATURES (0) to PLM XilOCP with @api_id as the query
+ * argument.  PLM returns success if that API is compiled-in and available.
+ *
+ * Return: 0 if supported, PLM error code if not supported or call failed.
+ */
+int zynqmp_pm_xilocp_is_feature_supported(u32 api_id)
+{
+	return xilinx_pm_request(PLM_IPI_HDR(1, XILOCP_MODULE_ID, XOCP_API_FEATURES),
+				 api_id, 0, 0, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_xilocp_extend_hwpcr() - Extend a Hardware PCR via PLM XilOCP.
+ * @pcr_num:   HW PCR index (0..7)
+ * @hash_addr: Physical address of the 48-byte hash buffer
+ *             (cache-flushed by caller)
+ * @size:      Buffer size in bytes (must be 48)
+ *
+ * Calls PLM XilOCP XOCP_API_EXTEND_HWPCR over the TF-A SMC PASS_THROUGH path.
+ *
+ * Return: 0 on success, PLM error code on failure.
+ */
+int zynqmp_pm_xilocp_extend_hwpcr(u32 pcr_num, u64 hash_addr, u32 size)
+{
+	int ret;
+
+	ret = xilinx_pm_request(PLM_IPI_HDR(4, XILOCP_MODULE_ID, XOCP_API_EXTEND_HWPCR),
+				pcr_num,
+				lower_32_bits(hash_addr),
+				upper_32_bits(hash_addr),
+				size, 0, 0, NULL);
+	if (ret)
+		printf("%s: HW PCR %u extend failed: %d\n",
+		       __func__, pcr_num, ret);
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_xilocp_get_hwpcr() - Read Hardware PCR value(s) via PLM XilOCP.
+ * @pcr_mask:  Bitmask of PCRs to read; bit N selects HW PCR N.
+ * @buf_addr:  Physical address of the output buffer (invalidated by caller)
+ * @buf_size:  Buffer size in bytes (48 * number of PCRs selected)
+ *
+ * Calls PLM XilOCP XOCP_API_GET_HWPCR over the TF-A SMC PASS_THROUGH path.
+ * PLM DMA-writes the PCR value(s) to buf_addr; caller must invalidate cache
+ * after this call before reading the buffer.
+ *
+ * Return: 0 on success, PLM error code on failure.
+ */
+int zynqmp_pm_xilocp_get_hwpcr(u32 pcr_mask, u64 buf_addr, u32 buf_size)
+{
+	int ret;
+
+	ret = xilinx_pm_request(PLM_IPI_HDR(4, XILOCP_MODULE_ID, XOCP_API_GET_HWPCR),
+				pcr_mask,
+				lower_32_bits(buf_addr),
+				upper_32_bits(buf_addr),
+				buf_size, 0, 0, NULL);
+	if (ret)
+		printf("%s: HW PCR mask 0x%x read failed: %d\n",
+		       __func__, pcr_mask, ret);
+
+	return ret;
+}
 #endif
 
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value)
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index 05df49f292a..4482517a970 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -529,4 +529,28 @@ extern smc_call_handler_t __data smc_call_handler;
 
 #define PM_DEV_OSPI		(0x1822402aU)
 
+/* XilOCP HW PCR API - Versal Gen 2 only */
+#define XILOCP_MODULE_ID		13U
+
+/*
+ * IPI payload header word passed as api_id to xilinx_pm_request().
+ *   bits [31:16] = payload length (number of arguments after the header)
+ *   bits [15:8]  = PLM module ID
+ *   bits [7:0]   = API function ID
+ *
+ * smc_call_enhanced() extracts module_id from bits[15:8] and fn_id from
+ * bits[7:0]; the len field is not encoded in the SMC call itself.
+ */
+#define PLM_IPI_HDR(len, module_id, api_id) \
+	(((u32)(len) << 16U) | ((u32)(module_id) << 8U) | (u32)(api_id))
+
+/* XilOCP API function IDs */
+#define XOCP_API_FEATURES		0U
+#define XOCP_API_EXTEND_HWPCR		1U
+#define XOCP_API_GET_HWPCR		2U
+
+int zynqmp_pm_xilocp_is_feature_supported(u32 api_id);
+int zynqmp_pm_xilocp_extend_hwpcr(u32 pcr_num, u64 hash_addr, u32 size);
+int zynqmp_pm_xilocp_get_hwpcr(u32 pcr_mask, u64 buf_addr, u32 buf_size);
+
 #endif /* _ZYNQMP_FIRMWARE_H_ */
-- 
2.34.1



More information about the U-Boot mailing list