{"id":2228246,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2228246/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260424173151.371134-3-harsimransingh.tungal@arm.com/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.1/projects/18/?format=json","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},"msgid":"<20260424173151.371134-3-harsimransingh.tungal@arm.com>","date":"2026-04-24T17:31:41","name":"[02/12] arm-ffa: add FF-A bus runtime support","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"9a1e255e639773fe00cd77fc1d170c04adeb2813","submitter":{"id":88701,"url":"http://patchwork.ozlabs.org/api/1.1/people/88701/?format=json","name":"Harsimran Singh Tungal","email":"harsimransingh.tungal@arm.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260424173151.371134-3-harsimransingh.tungal@arm.com/mbox/","series":[{"id":501471,"url":"http://patchwork.ozlabs.org/api/1.1/series/501471/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=501471","date":"2026-04-24T17:31:50","name":"arm64: FF-A runtime transport for EFI variables","version":1,"mbox":"http://patchwork.ozlabs.org/series/501471/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2228246/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2228246/checks/","tags":{},"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=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=arm.com header.i=@arm.com header.a=rsa-sha256\n header.s=foss header.b=dRSv31fM;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=85.214.62.61; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=fail (p=none dis=none) header.from=arm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=arm.com header.i=@arm.com header.b=\"dRSv31fM\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=arm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=harsimransingh.tungal@arm.com"],"Received":["from phobos.denx.de (phobos.denx.de [85.214.62.61])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g2yP928fvz1yHS\n\tfor <incoming@patchwork.ozlabs.org>; Sun, 26 Apr 2026 04:03:25 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 19E2384459;\n\tSat, 25 Apr 2026 20:02:46 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id 200DB843F9; Sat, 25 Apr 2026 19:01:49 +0200 (CEST)","from foss.arm.com (foss.arm.com [217.140.110.172])\n by phobos.denx.de (Postfix) with ESMTP id A6E14842C7\n for <u-boot@lists.denx.de>; Sat, 25 Apr 2026 19:01:45 +0200 (CEST)","from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14])\n by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0F21935A2;\n Fri, 24 Apr 2026 10:32:33 -0700 (PDT)","from e132995.arm.com (unknown [10.57.64.144])\n by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 920423F7B4;\n Fri, 24 Apr 2026 10:32:36 -0700 (PDT)"],"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,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED,\n SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss;\n t=1777051958; bh=4moB+AwxKihAevgoP1ltWpUCYEEwc6j+joYDk1KvyzY=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=dRSv31fMHXDzLf64gifsIR9lpUv0rM7qH7LFaC3FV4X/ngesaRn6R2cXntLqLcTqQ\n NzpqmIuvDABzWssqspUYlHCrlIkok2/a/ltIVrj1Ma2BMcqXl4Iw27aXIKg35RbYj/\n 4OXm/iirH/RZmBAy1xyCPCI5e4czAltM93/n9arY=","From":"Harsimran Singh Tungal <harsimransingh.tungal@arm.com>","To":"u-boot@lists.denx.de","Cc":"Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>,\n Tom Rini <trini@konsulko.com>,\n Ilias Apalodimas <ilias.apalodimas@linaro.org>,\n Heinrich Schuchardt <xypron.glpk@gmx.de>,\n Hugues Kamba Mpiana <hugues.kambampiana@arm.com>,\n Simon Glass <sjg@chromium.org>,\n Harsimran Singh Tungal <harsimransingh.tungal@arm.com>","Subject":"[PATCH 02/12] arm-ffa: add FF-A bus runtime support","Date":"Fri, 24 Apr 2026 18:31:41 +0100","Message-Id":"<20260424173151.371134-3-harsimransingh.tungal@arm.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20260424173151.371134-1-harsimransingh.tungal@arm.com>","References":"<20260424173151.371134-1-harsimransingh.tungal@arm.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","X-Mailman-Approved-At":"Sat, 25 Apr 2026 20:02:44 +0200","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":"Enable FF-A runtime transport for EFI services\n\nThis patch introduces the FF-A runtime infrastructure that enables\nU-Boot to use the Arm Firmware Framework for Arm A-profile (FF-A)\ntransport layer after ExitBootServices().\nThe runtime transport provides persistent, runtime-safe\nimplementations of key FF-A functions used by EFI runtime services.\n\nSummary of key changes:\n-----------------------\n  - Add drivers/firmware/arm-ffa/arm-ffa-runtime.c implementing FF-A\n    runtime operations.\n  - Introduce include/arm_ffa_runtime.h exporting FF-A runtime\n    functions and data structures.\n  - Move FF-A error mapping into runtime context.\n  - Introduce invoke_ffa_fn_runtime() as runtime safe SMC wrapper.\n  - Add runtime SMC wrapper for sandbox emulation.\n  - Add ARM_FFA_RT_MODE Kconfig to enable runtime support.\n  - Register ExitBootServices hook for runtime context.\n  - Copy ffa_priv runtime fields into resident storage at\n    ExitBootServices.\n  - Extend Makefile to build arm-ffa-runtime.c.\n\nAll runtime functions and global data are tagged with __efi_runtime or\n__efi_runtime_data to ensure persistence after ExitBootServices().\n\nSigned-off-by: Harsimran Singh Tungal <harsimransingh.tungal@arm.com>\n---\n drivers/firmware/arm-ffa/Kconfig           |  11 +\n drivers/firmware/arm-ffa/Makefile          |   4 +-\n drivers/firmware/arm-ffa/arm-ffa-runtime.c | 287 +++++++++++++++++++++\n drivers/firmware/arm-ffa/arm-ffa-uclass.c  | 111 ++------\n drivers/firmware/arm-ffa/arm-ffa.c         |  16 +-\n drivers/firmware/arm-ffa/ffa-emul-uclass.c |  12 +\n include/arm_ffa.h                          |  16 +-\n include/arm_ffa_priv.h                     |  24 +-\n include/arm_ffa_runtime.h                  | 183 +++++++++++++\n test/dm/ffa.c                              |   6 +-\n 10 files changed, 551 insertions(+), 119 deletions(-)\n create mode 100644 drivers/firmware/arm-ffa/arm-ffa-runtime.c\n create mode 100644 include/arm_ffa_runtime.h","diff":"diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig\nindex 3706a889305..7aaf25fdb58 100644\n--- a/drivers/firmware/arm-ffa/Kconfig\n+++ b/drivers/firmware/arm-ffa/Kconfig\n@@ -18,6 +18,9 @@ config ARM_FFA_TRANSPORT\n \t  The FF-A support in U-Boot is based on FF-A specification v1.0 and uses SMC32\n \t  calling convention.\n \n+\t  The FF-A bus also provides a runtime layer to keep a minimal set of FF-A\n+\t  operations available after ExitBootServices().\n+\n \t  FF-A specification:\n \n \t  https://developer.arm.com/documentation/den0077/a/?lang=en\n@@ -41,3 +44,11 @@ config ARM_FFA_TRANSPORT\n \t  Secure World (sandbox_ffa.c).\n \n \t  For more details about the FF-A support, please refer to doc/arch/arm64.ffa.rst\n+\n+config ARM_FFA_RT_MODE\n+\tbool \"Enable FF-A runtime support\"\n+\tdepends on ARM_FFA_TRANSPORT && EFI_LOADER\n+\tdefault y\n+\thelp\n+\t  Enable the FF-A runtime layer, keeping a minimal set of FF-A\n+\t  operations available after ExitBootServices().\ndiff --git a/drivers/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile\nindex 318123a7f42..9deb59ba640 100644\n--- a/drivers/firmware/arm-ffa/Makefile\n+++ b/drivers/firmware/arm-ffa/Makefile\n@@ -1,12 +1,12 @@\n # SPDX-License-Identifier: GPL-2.0+\n #\n-# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+# Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n #\n # Authors:\n #   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n \n # build the generic FF-A methods\n-obj-y += arm-ffa-uclass.o\n+obj-y += arm-ffa-uclass.o arm-ffa-runtime.o\n ifeq ($(CONFIG_SANDBOX),y)\n # build the FF-A sandbox emulator and driver\n obj-y += ffa-emul-uclass.o sandbox_ffa.o\ndiff --git a/drivers/firmware/arm-ffa/arm-ffa-runtime.c b/drivers/firmware/arm-ffa/arm-ffa-runtime.c\nnew file mode 100644\nindex 00000000000..3b80cce272b\n--- /dev/null\n+++ b/drivers/firmware/arm-ffa/arm-ffa-runtime.c\n@@ -0,0 +1,287 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ *\n+ * Authors:\n+ *      Harsimran Singh Tungal <harsimransingh.tungal@arm.com>\n+ *      Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n+ */\n+\n+#include <arm_ffa_runtime.h>\n+#include <arm_ffa_priv.h>\n+#include <log.h>\n+#include <asm/global_data.h>\n+#include <linux/errno.h>\n+#include <linux/types.h>\n+\n+DECLARE_GLOBAL_DATA_PTR;\n+\n+/* Error mapping declarations */\n+\n+int __ffa_runtime_data ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {\n+\t[NOT_SUPPORTED] = -EOPNOTSUPP,\n+\t[INVALID_PARAMETERS] = -EINVAL,\n+\t[NO_MEMORY] = -ENOMEM,\n+\t[BUSY] = -EBUSY,\n+\t[INTERRUPTED] = -EINTR,\n+\t[DENIED] = -EACCES,\n+\t[RETRY] = -EAGAIN,\n+\t[ABORTED] = -ECANCELED,\n+};\n+\n+static __ffa_runtime_data struct ffa_priv_runtime ffa_priv_rt = {0};\n+\n+/* Arm FF-A driver runtime operations */\n+static const __ffa_runtime_data struct ffa_bus_ops_runtime ffa_ops_rt = {\n+\t.sync_send_receive = ffa_msg_send_direct_req_hdlr_runtime,\n+};\n+\n+#define ffa_get_ops_runtime()\t\t(&ffa_ops_rt)\n+#define ffa_get_priv_runtime()\t\t(&ffa_priv_rt)\n+\n+#if CONFIG_IS_ENABLED(ARM_FFA_RT_MODE)\n+static void EFIAPI ffa_rt_exit_boot_services_notify(struct efi_event *event,\n+\t\t\t\t\t\t    void *context)\n+{\n+\tstruct ffa_priv *priv = context;\n+\n+\tif (priv)\n+\t\tffa_copy_runtime_priv(&priv->rt);\n+\telse\n+\t\tlog_err(\"FF-A: Entering RT mode without FF-A runtime data information\\n\");\n+\n+\tffa_enable_runtime_context();\n+}\n+\n+/**\n+ * ffa_setup_efi_exit_boot_services_event() - register ExitBootServices event\n+ * @priv: pointer to the FF-A private data\n+ *\n+ * Register an EFI event that enables the FF-A runtime context when\n+ * ExitBootServices() is invoked.\n+ *\n+ * Return: 0 on success, -EPERM on failure to create the event.\n+ */\n+int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv)\n+{\n+\tefi_status_t efi_ret;\n+\tstruct efi_event *evt = NULL;\n+\n+\tefi_ret = efi_create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\n+\t\t\t\t   ffa_rt_exit_boot_services_notify, priv,\n+\t\t\t\t   &efi_guid_event_group_exit_boot_services,\n+\t\t\t\t   &evt);\n+\tif (efi_ret != EFI_SUCCESS) {\n+\t\tlog_err(\"FF-A: cannot install ExitBootServices event %p, err (%lu)\\n\",\n+\t\t\tevt, efi_ret);\n+\t\treturn -EPERM;\n+\t}\n+\n+\treturn 0;\n+}\n+#endif\n+\n+/**\n+ * ffa_copy_runtime_priv() - copy runtime data into resident storage\n+ * @priv: pointer to the runtime private data\n+ *\n+ * Copy boot-time runtime data into the resident runtime storage to be used\n+ * after ExitBootServices().\n+ */\n+void ffa_copy_runtime_priv(const struct ffa_priv_runtime *priv)\n+{\n+\tstruct ffa_priv_runtime *priv_rt = ffa_get_priv_runtime();\n+\n+\tif (priv)\n+\t\t*priv_rt = *priv;\n+}\n+\n+/**\n+ * ffa_enable_runtime_context() - Enable FF-A runtime context\n+ *\n+ * This function marks the FF-A runtime environment as ready for use by\n+ * EFI runtime services. It is called when ExitBootServices() is invoked,\n+ * after the FF-A bus device has successfully probed and U-Boot’s FF-A\n+ * endpoint ID has been discovered and stored in the runtime private data\n+ * structure.\n+ *\n+ * The FF-A runtime flag allows the EFI runtime layer to verify that the\n+ * FF-A transport was initialized during the boot phase and that all\n+ * runtime-safe FF-A operations may now be used after ExitBootServices().\n+ *\n+ */\n+void ffa_enable_runtime_context(void)\n+{\n+\tstruct ffa_priv_runtime *priv_rt = ffa_get_priv_runtime();\n+\n+\tpriv_rt->use_ffa_runtime = true;\n+}\n+\n+/**\n+ * ffa_get_status_runtime_context() - Query FF-A runtime readiness\n+ *\n+ * This helper returns whether the FF-A runtime environment has been\n+ * enabled during the boot phase. Runtime FF-A operations must check this\n+ * flag before attempting any FF-A access, as the U-Boot driver model\n+ * (DM/uclass) is no longer available after ExitBootServices().\n+ *\n+ * The runtime context becomes enabled when ffa_enable_runtime_context()\n+ * is called, typically after the FF-A bus device has probed and the\n+ * endpoint ID has been discovered and stored in the runtime private\n+ * data structure.\n+ *\n+ * Return: true if FF-A runtime support is ready, false otherwise.\n+ */\n+bool __ffa_runtime ffa_get_status_runtime_context(void)\n+{\n+\tstruct ffa_priv_runtime *priv_rt = ffa_get_priv_runtime();\n+\n+\treturn priv_rt->use_ffa_runtime;\n+}\n+\n+/**\n+ * ffa_to_std_errno() - convert FF-A error code to standard error code\n+ * @ffa_errno:\tError code returned by the FF-A ABI\n+ *\n+ * Map the given FF-A error code as specified\n+ * by the spec to a u-boot standard error code.\n+ *\n+ * Return: Standard U-Boot errno for known FF-A errors, or -EINVAL otherwise.\n+ */\n+int __ffa_runtime ffa_to_std_errno(int ffa_errno)\n+{\n+\tint err_idx = -ffa_errno;\n+\n+\t/* Map the FF-A error code to the standard u-boot error code */\n+\tif (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)\n+\t\treturn ffa_to_std_errmap[err_idx];\n+\treturn -EINVAL;\n+}\n+\n+/**\n+ * ffa_invoke_msg_send_direct_req() - Invokes FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ * @endpoint_id: u-boot endpoint id\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * This function invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n+ *\n+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.\n+ * The response from the secure partition is handled by reading the\n+ * FFA_MSG_SEND_DIRECT_RESP arguments.\n+ *\n+ * The maximum size of the data that can be exchanged is 40 bytes which is\n+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0\n+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ *\n+ * Return: 0 on success, negative errno on failure.\n+ */\n+int __ffa_runtime ffa_invoke_msg_send_direct_req(u16 endpoint_id, u16 dst_part_id,\n+\t\t\t\t\t\t struct ffa_send_direct_data *msg, bool is_smc64)\n+{\n+\tint ffa_errno;\n+\tu64 req_mode;\n+\tffa_value_t ffa_args_rt;\n+\tffa_value_t ffa_res_rt;\n+\n+\tif (is_smc64) {\n+\t\treq_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);\n+\t} else {\n+\t\treq_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);\n+\t}\n+\n+\tefi_memset_runtime(&ffa_args_rt, 0, sizeof(ffa_args_rt));\n+\tefi_memset_runtime(&ffa_res_rt, 0, sizeof(ffa_res_rt));\n+\tffa_args_rt.a0 = req_mode;\n+\tffa_args_rt.a1 = PREP_SELF_ENDPOINT_ID(endpoint_id) |\n+\t\t\t PREP_PART_ENDPOINT_ID(dst_part_id);\n+\tffa_args_rt.a2 = 0;\n+\tffa_args_rt.a3 = msg->data0;\n+\tffa_args_rt.a4 = msg->data1;\n+\tffa_args_rt.a5 = msg->data2;\n+\tffa_args_rt.a6 = msg->data3;\n+\tffa_args_rt.a7 = msg->data4;\n+\n+\tinvoke_ffa_fn_runtime(&ffa_args_rt, &ffa_res_rt);\n+\n+\twhile (ffa_res_rt.a0 == FFA_SMC_32(FFA_INTERRUPT) ||\n+\t       ffa_res_rt.a0 == FFA_SMC_64(FFA_INTERRUPT)) {\n+\t\tefi_memset_runtime(&ffa_args_rt, 0, sizeof(ffa_args_rt));\n+\t\tffa_args_rt.a0 = (ffa_res_rt.a0 == FFA_SMC_64(FFA_INTERRUPT)) ?\n+\t\t\t\t  FFA_SMC_64(FFA_RUN) : FFA_SMC_32(FFA_RUN);\n+\t\tffa_args_rt.a1 = ffa_res_rt.a1;\n+\n+\t\tinvoke_ffa_fn_runtime(&ffa_args_rt, &ffa_res_rt);\n+\t}\n+\tif (ffa_res_rt.a0 == FFA_SMC_32(FFA_SUCCESS) ||\n+\t    ffa_res_rt.a0 == FFA_SMC_64(FFA_SUCCESS)) {\n+\t\t/* Message sent with no response */\n+\t\treturn 0;\n+\t}\n+\n+\tif (ffa_res_rt.a0 == FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP) ||\n+\t    ffa_res_rt.a0 == FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP)) {\n+\t\t/* Message sent with response extract the return data */\n+\t\tmsg->data0 = ffa_res_rt.a3;\n+\t\tmsg->data1 = ffa_res_rt.a4;\n+\t\tmsg->data2 = ffa_res_rt.a5;\n+\t\tmsg->data3 = ffa_res_rt.a6;\n+\t\tmsg->data4 = ffa_res_rt.a7;\n+\t\treturn 0;\n+\t}\n+\n+\tffa_errno = ffa_res_rt.a2;\n+\treturn ffa_to_std_errno(ffa_errno);\n+}\n+\n+/**\n+ * ffa_msg_send_direct_req_hdlr_runtime() - Runtime implementation of\n+ * FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * This function calls the ffa_invoke_msg_send_direct_req() function which\n+ * invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n+ *\n+ * Return:\n+ *\n+ * 0 on success. Otherwise, failure\n+ */\n+int __ffa_runtime ffa_msg_send_direct_req_hdlr_runtime(u16 dst_part_id,\n+\t\t\t\t\t\t       struct ffa_send_direct_data *msg,\n+\t\t\t\t\t\t       bool is_smc64)\n+{\n+\tstruct ffa_priv_runtime *priv_rt = ffa_get_priv_runtime();\n+\n+\treturn ffa_invoke_msg_send_direct_req(priv_rt->id, dst_part_id, msg, is_smc64);\n+}\n+\n+/**\n+ * ffa_sync_send_receive_runtime() - Runtime implementation of\n+ *                              ffa_sync_send_receive()\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * Please see ffa_msg_send_direct_req_hdlr_runtime() description for more details.\n+ *\n+ * Return:\n+ *\n+ * 0 on success. Otherwise, failure\n+ */\n+int __ffa_runtime ffa_sync_send_receive_runtime(u16 dst_part_id,\n+\t\t\t\t\t\tstruct ffa_send_direct_data *msg,\n+\t\t\t\t\t\tbool is_smc64)\n+{\n+\tconst struct ffa_bus_ops_runtime *ops_rt = ffa_get_ops_runtime();\n+\n+\tif (!ffa_get_status_runtime_context())\n+\t\treturn -EPERM;\n+\n+\tif (!ops_rt->sync_send_receive)\n+\t\treturn -ENOSYS;\n+\n+\treturn ops_rt->sync_send_receive(dst_part_id, msg, is_smc64);\n+}\ndiff --git a/drivers/firmware/arm-ffa/arm-ffa-uclass.c b/drivers/firmware/arm-ffa/arm-ffa-uclass.c\nindex 76a8775e911..af04ba1bcbc 100644\n--- a/drivers/firmware/arm-ffa/arm-ffa-uclass.c\n+++ b/drivers/firmware/arm-ffa/arm-ffa-uclass.c\n@@ -1,12 +1,13 @@\n // SPDX-License-Identifier: GPL-2.0+\n /*\n- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ * Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n  *\n  * Authors:\n  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n  */\n #include <arm_ffa.h>\n #include <arm_ffa_priv.h>\n+#include <arm_ffa_runtime.h>\n #include <dm.h>\n #include <log.h>\n #include <malloc.h>\n@@ -18,19 +19,6 @@\n #include <linux/errno.h>\n #include <linux/sizes.h>\n \n-/* Error mapping declarations */\n-\n-int ffa_to_std_errmap[MAX_NUMBER_FFA_ERR] = {\n-\t[NOT_SUPPORTED] = -EOPNOTSUPP,\n-\t[INVALID_PARAMETERS] = -EINVAL,\n-\t[NO_MEMORY] = -ENOMEM,\n-\t[BUSY] = -EBUSY,\n-\t[INTERRUPTED] = -EINTR,\n-\t[DENIED] = -EACCES,\n-\t[RETRY] = -EAGAIN,\n-\t[ABORTED] = -ECANCELED,\n-};\n-\n static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {\n \t[FFA_ID_TO_ERRMAP_ID(FFA_VERSION)] = {\n \t\t{\n@@ -94,27 +82,6 @@ static struct ffa_abi_errmap err_msg_map[FFA_ERRMAP_COUNT] = {\n \t},\n };\n \n-/**\n- * ffa_to_std_errno() - convert FF-A error code to standard error code\n- * @ffa_errno:\tError code returned by the FF-A ABI\n- *\n- * Map the given FF-A error code as specified\n- * by the spec to a u-boot standard error code.\n- *\n- * Return:\n- *\n- * The standard error code on success. . Otherwise, failure\n- */\n-static int ffa_to_std_errno(int ffa_errno)\n-{\n-\tint err_idx = -ffa_errno;\n-\n-\t/* Map the FF-A error code to the standard u-boot error code */\n-\tif (err_idx > 0 && err_idx < MAX_NUMBER_FFA_ERR)\n-\t\treturn ffa_to_std_errmap[err_idx];\n-\treturn -EINVAL;\n-}\n-\n /**\n  * ffa_print_error_log() - print the error log corresponding to the selected FF-A ABI\n  * @ffa_id:\tFF-A ABI ID\n@@ -204,7 +171,7 @@ int ffa_get_version_hdlr(struct udevice *dev)\n \t\tif (dev) {\n \t\t\tuc_priv = dev_get_uclass_priv(dev);\n \t\t\tif (uc_priv)\n-\t\t\t\tuc_priv->fwk_version = res.a0;\n+\t\t\t\tuc_priv->rt.fwk_version = res.a0;\n \t\t}\n \n \t\treturn 0;\n@@ -238,8 +205,8 @@ static int ffa_get_endpoint_id(struct udevice *dev)\n \t\t\t}, &res);\n \n \tif (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {\n-\t\tuc_priv->id = GET_SELF_ENDPOINT_ID((u32)res.a2);\n-\t\tlog_debug(\"FF-A endpoint ID is %u\\n\", uc_priv->id);\n+\t\tuc_priv->rt.id = GET_SELF_ENDPOINT_ID((u32)res.a2);\n+\t\tlog_debug(\"FF-A endpoint ID is %u\\n\", uc_priv->rt.id);\n \n \t\treturn 0;\n \t}\n@@ -461,7 +428,7 @@ int ffa_unmap_rxtx_buffers_hdlr(struct udevice *dev)\n \n \tinvoke_ffa_fn((ffa_value_t){\n \t\t\t.a0 = FFA_SMC_32(FFA_RXTX_UNMAP),\n-\t\t\t.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id),\n+\t\t\t.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->rt.id),\n \t\t\t}, &res);\n \n \tif (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {\n@@ -851,16 +818,8 @@ static int ffa_cache_partitions_info(struct udevice *dev)\n  * @msg: pointer to the message data preallocated by the client (in/out)\n  * @is_smc64: select 64-bit or 32-bit FF-A ABI\n  *\n- * Implement FFA_MSG_SEND_DIRECT_{REQ,RESP}\n- * FF-A functions.\n- *\n- * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.\n- * The response from the secure partition is handled by reading the\n- * FFA_MSG_SEND_DIRECT_RESP arguments.\n- *\n- * The maximum size of the data that can be exchanged is 40 bytes which is\n- * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0\n- * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ * This function calls the ffa_invoke_msg_send_direct_req() function which\n+ * invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n  *\n  * Return:\n  *\n@@ -869,9 +828,6 @@ static int ffa_cache_partitions_info(struct udevice *dev)\n int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,\n \t\t\t\t struct ffa_send_direct_data *msg, bool is_smc64)\n {\n-\tffa_value_t res = {0};\n-\tint ffa_errno;\n-\tu64 req_mode, resp_mode;\n \tstruct ffa_priv *uc_priv;\n \n \tuc_priv = dev_get_uclass_priv(dev);\n@@ -880,50 +836,7 @@ int ffa_msg_send_direct_req_hdlr(struct udevice *dev, u16 dst_part_id,\n \tif (!uc_priv->partitions.count || !uc_priv->partitions.descs)\n \t\treturn -ENODEV;\n \n-\tif (is_smc64) {\n-\t\treq_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ);\n-\t\tresp_mode = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);\n-\t} else {\n-\t\treq_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_REQ);\n-\t\tresp_mode = FFA_SMC_32(FFA_MSG_SEND_DIRECT_RESP);\n-\t}\n-\n-\tinvoke_ffa_fn((ffa_value_t){\n-\t\t\t.a0 = req_mode,\n-\t\t\t.a1 = PREP_SELF_ENDPOINT_ID(uc_priv->id) |\n-\t\t\t\tPREP_PART_ENDPOINT_ID(dst_part_id),\n-\t\t\t.a2 = 0,\n-\t\t\t.a3 = msg->data0,\n-\t\t\t.a4 = msg->data1,\n-\t\t\t.a5 = msg->data2,\n-\t\t\t.a6 = msg->data3,\n-\t\t\t.a7 = msg->data4,\n-\t\t\t}, &res);\n-\n-\twhile (res.a0 == FFA_SMC_32(FFA_INTERRUPT))\n-\t\tinvoke_ffa_fn((ffa_value_t){\n-\t\t\t.a0 = FFA_SMC_32(FFA_RUN),\n-\t\t\t.a1 = res.a1,\n-\t\t\t}, &res);\n-\n-\tif (res.a0 == FFA_SMC_32(FFA_SUCCESS)) {\n-\t\t/* Message sent with no response */\n-\t\treturn 0;\n-\t}\n-\n-\tif (res.a0 == resp_mode) {\n-\t\t/* Message sent with response extract the return data */\n-\t\tmsg->data0 = res.a3;\n-\t\tmsg->data1 = res.a4;\n-\t\tmsg->data2 = res.a5;\n-\t\tmsg->data3 = res.a6;\n-\t\tmsg->data4 = res.a7;\n-\n-\t\treturn 0;\n-\t}\n-\n-\tffa_errno = res.a2;\n-\treturn ffa_to_std_errno(ffa_errno);\n+\treturn ffa_invoke_msg_send_direct_req(uc_priv->rt.id, dst_part_id, msg, is_smc64);\n }\n \n /* FF-A driver operations (used by clients for communicating with FF-A)*/\n@@ -1024,6 +937,7 @@ int ffa_rxtx_unmap(struct udevice *dev)\n static int ffa_do_probe(struct udevice *dev)\n {\n \tint ret;\n+\tstruct ffa_priv *uc_priv = dev_get_uclass_priv(dev);\n \n \tret = ffa_get_version_hdlr(dev);\n \tif (ret)\n@@ -1047,6 +961,11 @@ static int ffa_do_probe(struct udevice *dev)\n \t\treturn ret;\n \t}\n \n+\tif (IS_ENABLED(CONFIG_ARM_FFA_RT_MODE)) {\n+\t\tret = ffa_setup_efi_exit_boot_services_event(uc_priv);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n \treturn 0;\n }\n \ndiff --git a/drivers/firmware/arm-ffa/arm-ffa.c b/drivers/firmware/arm-ffa/arm-ffa.c\nindex 9e6b5dcc542..241ef018817 100644\n--- a/drivers/firmware/arm-ffa/arm-ffa.c\n+++ b/drivers/firmware/arm-ffa/arm-ffa.c\n@@ -1,6 +1,6 @@\n // SPDX-License-Identifier: GPL-2.0+\n /*\n- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ * Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n  *\n  * Authors:\n  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n@@ -8,6 +8,7 @@\n \n #include <arm_ffa.h>\n #include <arm_ffa_priv.h>\n+#include <arm_ffa_runtime.h>\n #include <dm.h>\n #include <log.h>\n #include <dm/device-internal.h>\n@@ -25,6 +26,19 @@ void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)\n \tarm_smccc_1_2_smc(&args, res);\n }\n \n+/**\n+ * invoke_ffa_fn_runtime() - Runtime-safe SMC wrapper\n+ * @args: FF-A ABI arguments to be copied to Xn registers\n+ * @res:  FF-A ABI return values copied from Xn registers\n+ *\n+ * Calls the SMCCC SMC 1.2 helper from EFI runtime context. This wrapper\n+ * is marked __ffa_runtime so it remains available after ExitBootServices().\n+ */\n+void __ffa_runtime invoke_ffa_fn_runtime(ffa_value_t *args, ffa_value_t *res)\n+{\n+\tarm_smccc_1_2_smc(args, res);\n+}\n+\n /**\n  * arm_ffa_discover() - perform FF-A discovery\n  * @dev: The Arm FF-A bus device (arm_ffa)\ndiff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c b/drivers/firmware/arm-ffa/ffa-emul-uclass.c\nindex 6198d687354..d270f7b614e 100644\n--- a/drivers/firmware/arm-ffa/ffa-emul-uclass.c\n+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c\n@@ -671,6 +671,18 @@ void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res)\n \tsandbox_arm_ffa_smccc_smc(&args, res);\n }\n \n+/**\n+ * invoke_ffa_fn_runtime() - Runtime-safe SMC wrapper\n+ * @args: FF-A ABI arguments to be copied to Xn registers\n+ * @res: FF-A ABI return data to be copied from Xn registers\n+ *\n+ * Calls the emulated SMC call.\n+ */\n+void invoke_ffa_fn_runtime(ffa_value_t *args, ffa_value_t *res)\n+{\n+\tsandbox_arm_ffa_smccc_smc(args, res);\n+}\n+\n /**\n  * ffa_emul_find() - Find the FF-A emulator\n  * @dev:\tthe sandbox FF-A device (sandbox-arm-ffa)\ndiff --git a/include/arm_ffa.h b/include/arm_ffa.h\nindex 2994d8ee3ae..6a03aad81a8 100644\n--- a/include/arm_ffa.h\n+++ b/include/arm_ffa.h\n@@ -1,6 +1,6 @@\n /* SPDX-License-Identifier: GPL-2.0+ */\n /*\n- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ * Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n  *\n  * Authors:\n  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n@@ -129,21 +129,13 @@ int ffa_sync_send_receive(struct udevice *dev, u16 dst_part_id,\n \n /**\n  * ffa_msg_send_direct_req_hdlr() - FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function\n- * @dev: The arm_ffa bus device\n+ * @dev: The FF-A bus device\n  * @dst_part_id: destination partition ID\n  * @msg: pointer to the message data preallocated by the client (in/out)\n  * @is_smc64: select 64-bit or 32-bit FF-A ABI\n  *\n- * This function implements FFA_MSG_SEND_DIRECT_{REQ,RESP}\n- * FF-A functions.\n- *\n- * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.\n- * The response from the secure partition is handled by reading the\n- * FFA_MSG_SEND_DIRECT_RESP arguments.\n- *\n- * The maximum size of the data that can be exchanged is 40 bytes which is\n- * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0\n- * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ * This function calls the ffa_invoke_msg_send_direct_req() function which\n+ * invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n  *\n  * Return:\n  *\ndiff --git a/include/arm_ffa_priv.h b/include/arm_ffa_priv.h\nindex d564c33c647..87c6abe4299 100644\n--- a/include/arm_ffa_priv.h\n+++ b/include/arm_ffa_priv.h\n@@ -1,6 +1,6 @@\n /* SPDX-License-Identifier: GPL-2.0+ */\n /*\n- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ * Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n  *\n  * Authors:\n  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n@@ -200,11 +200,26 @@ struct ffa_partitions {\n };\n \n /**\n- * struct ffa_priv - the driver private data structure\n+ * struct ffa_priv_runtime - the driver's private runtime data structure\n  *\n+ * @use_ffa_runtime:\tWhether FF-A runtime is available to use or not\n  * @fwk_version:\tFF-A framework version\n- * @emul:\tFF-A sandbox emulator\n  * @id:\tu-boot endpoint ID\n+ *\n+ * The device private runtime data structure containing all the\n+ * data read from secure world.\n+ */\n+struct ffa_priv_runtime {\n+\tbool use_ffa_runtime;\n+\tu32 fwk_version;\n+\tu16 id;\n+};\n+\n+/**\n+ * struct ffa_priv - the driver private data structure\n+ *\n+ * @rt:\t\tRuntime data captured at boot time\n+ * @emul:\tFF-A sandbox emulator\n  * @partitions:\tThe partitions descriptors structure\n  * @pair:\tThe RX/TX buffers pair\n  *\n@@ -212,9 +227,8 @@ struct ffa_partitions {\n  * data read from secure world.\n  */\n struct ffa_priv {\n-\tu32 fwk_version;\n+\tstruct ffa_priv_runtime rt;\n \tstruct udevice *emul;\n-\tu16 id;\n \tstruct ffa_partitions partitions;\n \tstruct ffa_rxtxpair pair;\n };\ndiff --git a/include/arm_ffa_runtime.h b/include/arm_ffa_runtime.h\nnew file mode 100644\nindex 00000000000..5fc411192ab\n--- /dev/null\n+++ b/include/arm_ffa_runtime.h\n@@ -0,0 +1,183 @@\n+/* SPDX-License-Identifier: GPL-2.0+ */\n+/*\n+ * Copyright 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ *\n+ * Authors:\n+ *   Harsimran Singh Tungal <harsimransingh.tungal@arm.com>\n+ *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n+ */\n+\n+#ifndef __ARM_FFA_RUNTIME_H\n+#define __ARM_FFA_RUNTIME_H\n+\n+#include <linux/types.h>\n+#include <arm_ffa.h>\n+#include <arm_ffa_priv.h>\n+#include <efi_loader.h>\n+\n+/**\n+ *  __ffa_runtime - controls whether functions are\n+ * available after calling the EFI ExitBootServices service.\n+ * Functions tagged with these keywords are resident (available at boot time and\n+ * at runtime)\n+ */\n+#if CONFIG_IS_ENABLED(ARM_FFA_RT_MODE)\n+#define __ffa_runtime_data __efi_runtime_data\n+#define __ffa_runtime __efi_runtime\n+#else\n+#define __ffa_runtime_data\n+#define __ffa_runtime\n+#endif\n+\n+/**\n+ * invoke_ffa_fn_runtime() - Runtime-safe SMC wrapper\n+ * @args: FF-A ABI arguments to be copied to Xn registers\n+ * @res:  FF-A ABI return values copied from Xn registers\n+ *\n+ * Calls low level SMC implementation. This wrapper\n+ * is marked __ffa_runtime so it remains available after ExitBootServices().\n+ */\n+void __ffa_runtime invoke_ffa_fn_runtime(ffa_value_t *args, ffa_value_t *res);\n+\n+/**\n+ * struct ffa_bus_ops_runtime - Operations for FF-A runtime\n+ * @sync_send_receive:\tcallback for the FFA_MSG_SEND_DIRECT_REQ\n+ *\n+ * The data structure providing all the runtime operations supported by the driver.\n+ * This structure is an EFI runtime resident.\n+ */\n+struct ffa_bus_ops_runtime {\n+\tint (*sync_send_receive)(u16 dst_part_id, struct ffa_send_direct_data *msg,\n+\t\t\t\t bool is_smc64);\n+};\n+\n+/**\n+ * ffa_enable_runtime_context() - Enable FF-A runtime context\n+ *\n+ * This function marks the FF-A runtime environment as ready for use by\n+ * EFI runtime services. It is called when ExitBootServices() is invoked,\n+ * after the FF-A bus device has successfully probed and U-Boot’s FF-A\n+ * endpoint ID has been discovered and stored in the runtime private data\n+ * structure.\n+ *\n+ * The FF-A runtime flag allows the EFI runtime layer to verify that the\n+ * FF-A transport was initialized during the boot phase and that all\n+ * runtime-safe FF-A operations may now be used after ExitBootServices().\n+ *\n+ */\n+void ffa_enable_runtime_context(void);\n+\n+/**\n+ * ffa_copy_runtime_priv() - copy runtime data into resident storage\n+ * @priv: pointer to the runtime private data\n+ *\n+ * Copy boot-time runtime data into the resident runtime storage to be used\n+ * after ExitBootServices().\n+ */\n+void ffa_copy_runtime_priv(const struct ffa_priv_runtime *priv);\n+\n+/**\n+ * ffa_setup_efi_exit_boot_services_event() - register ExitBootServices event\n+ * @priv: pointer to the FF-A private data\n+ *\n+ * Register an EFI event that enables the FF-A runtime context when\n+ * ExitBootServices() is invoked.\n+ *\n+ * Return: 0 on success, -EPERM on failure to create the event.\n+ */\n+#if CONFIG_IS_ENABLED(ARM_FFA_RT_MODE)\n+int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv);\n+#else\n+static inline int ffa_setup_efi_exit_boot_services_event(struct ffa_priv *priv)\n+{\n+\treturn 0;\n+}\n+#endif\n+\n+/**\n+ * ffa_get_status_runtime_context() - Query FF-A runtime readiness\n+ *\n+ * This helper returns whether the FF-A runtime environment has been\n+ * enabled during the boot phase. Runtime FF-A operations must check this\n+ * flag before attempting any FF-A access, as the U-Boot driver model\n+ * (DM/uclass) is no longer available after ExitBootServices().\n+ *\n+ * The runtime context becomes enabled when ffa_enable_runtime_context()\n+ * is called, typically after the FF-A bus device has probed and the\n+ * endpoint ID has been discovered and stored in the runtime private\n+ * data structure.\n+ *\n+ * Return: true if FF-A runtime support is ready, false otherwise.\n+ */\n+bool __ffa_runtime ffa_get_status_runtime_context(void);\n+\n+/**\n+ * ffa_to_std_errno() - convert FF-A error code to standard error code\n+ * @ffa_errno:\tError code returned by the FF-A ABI\n+ *\n+ * Map the given FF-A error code as specified\n+ * by the spec to a u-boot standard error code.\n+ *\n+ * Return: Standard U-Boot errno for known FF-A errors, or -EINVAL otherwise.\n+ */\n+int __ffa_runtime ffa_to_std_errno(int ffa_errno);\n+\n+/**\n+ * ffa_sync_send_receive_runtime() - Runtime implementation of\n+ *                              ffa_sync_send_receive()\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * Please see ffa_msg_send_direct_req_hdlr_runtime() description for more details.\n+ *\n+ * Return: 0 on success, negative errno on failure.\n+ */\n+int __ffa_runtime ffa_sync_send_receive_runtime(u16 dst_part_id,\n+\t\t\t\t\t\tstruct ffa_send_direct_data *msg,\n+\t\t\t\t\t\tbool is_smc64);\n+\n+/**\n+ * ffa_invoke_msg_send_direct_req() - Invokes FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ * @endpoint_id: u-boot endpoint id\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * This function invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n+ *\n+ * FFA_MSG_SEND_DIRECT_REQ is used to send the data to the secure partition.\n+ * The response from the secure partition is handled by reading the\n+ * FFA_MSG_SEND_DIRECT_RESP arguments.\n+ *\n+ * The maximum size of the data that can be exchanged is 40 bytes which is\n+ * sizeof(struct ffa_send_direct_data) as defined by the FF-A specification 1.0\n+ * in the section relevant to FFA_MSG_SEND_DIRECT_{REQ,RESP}\n+ *\n+ * Return:\n+ *\n+ * 0 on success. Otherwise, error on failure\n+ */\n+int __ffa_runtime ffa_invoke_msg_send_direct_req(u16 endpoint_id, u16 dst_part_id,\n+\t\t\t\t\t\t struct ffa_send_direct_data *msg,\n+\t\t\t\t\t\t bool is_smc64);\n+\n+/**\n+ * ffa_msg_send_direct_req_hdlr_runtime() - Runtime implementation of\n+ * FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function\n+ * @dst_part_id: destination partition ID\n+ * @msg: pointer to the message data preallocated by the client (in/out)\n+ * @is_smc64: select 64-bit or 32-bit FF-A ABI\n+ *\n+ * This function calls the ffa_invoke_msg_send_direct_req() function which\n+ * invokes FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A functions.\n+ *\n+ * Return:\n+ *\n+ * 0 on success. Otherwise, failure\n+ */\n+int __ffa_runtime ffa_msg_send_direct_req_hdlr_runtime(u16 dst_part_id,\n+\t\t\t\t\t\t       struct ffa_send_direct_data *msg,\n+\t\t\t\t\t\t       bool is_smc64);\n+\n+#endif\ndiff --git a/test/dm/ffa.c b/test/dm/ffa.c\nindex 593b7177fce..a0c95e62607 100644\n--- a/test/dm/ffa.c\n+++ b/test/dm/ffa.c\n@@ -2,7 +2,7 @@\n /*\n  * Functional tests for UCLASS_FFA  class\n  *\n- * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>\n+ * Copyright 2022-2023, 2026 Arm Limited and/or its affiliates <open-source-office@arm.com>\n  *\n  * Authors:\n  *   Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>\n@@ -26,14 +26,14 @@ static int check_fwk_version(struct ffa_priv *uc_priv, struct unit_test_state *u\n \tfunc_data.data0 = &fwk_version;\n \tfunc_data.data0_size = sizeof(fwk_version);\n \tut_assertok(sandbox_query_ffa_emul_state(FFA_VERSION, &func_data));\n-\tut_asserteq(uc_priv->fwk_version, fwk_version);\n+\tut_asserteq(uc_priv->rt.fwk_version, fwk_version);\n \n \treturn 0;\n }\n \n static int check_endpoint_id(struct ffa_priv *uc_priv, struct unit_test_state *uts)\n {\n-\tut_asserteq(0, uc_priv->id);\n+\tut_asserteq(0, uc_priv->rt.id);\n \n \treturn 0;\n }\n","prefixes":["02/12"]}