[PATCH v2 3/6] arm_ffa: introduce the FF-A Sandbox driver

abdellatif.elkhlifi at arm.com abdellatif.elkhlifi at arm.com
Fri Apr 15 14:28:00 CEST 2022


From: Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>

Provide a Sandbox driver to emulate the FF-A ABIs

The emulated ABIs are those supported by the FF-A core driver
and according to FF-A specification v1.0.

The Sandbox driver provides operations allowing the test
application to read the status of all the inspected ABIs
and perform functional tests based on that.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
---
 MAINTAINERS                           |   2 +
 common/board_r.c                      |   2 +-
 configs/sandbox64_defconfig           |   2 +
 configs/sandbox_defconfig             |   2 +
 doc/arch/sandbox.rst                  |   1 +
 drivers/arm-ffa/Kconfig               |   8 +-
 drivers/arm-ffa/Makefile              |   1 +
 drivers/arm-ffa/arm-ffa-uclass.c      |  47 +-
 drivers/arm-ffa/core.c                |  97 ++--
 drivers/arm-ffa/sandbox.c             | 669 ++++++++++++++++++++++++++
 drivers/arm-ffa/sandbox_arm_ffa_prv.h | 131 +++++
 include/arm_ffa.h                     |   9 +-
 include/sandbox_arm_ffa.h             |  31 ++
 include/sandbox_arm_ffa_helper.h      |  26 +
 lib/arm-ffa/Makefile                  |   1 +
 lib/arm-ffa/arm_ffa_helper.c          |   2 +-
 lib/arm-ffa/sandbox_arm_ffa_helper.c  |  23 +
 lib/efi_loader/efi_boottime.c         |   4 +-
 18 files changed, 1017 insertions(+), 41 deletions(-)
 create mode 100644 drivers/arm-ffa/sandbox.c
 create mode 100644 drivers/arm-ffa/sandbox_arm_ffa_prv.h
 create mode 100644 include/sandbox_arm_ffa.h
 create mode 100644 include/sandbox_arm_ffa_helper.h
 create mode 100644 lib/arm-ffa/sandbox_arm_ffa_helper.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ca2e13b9ec..7c439ed1fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -239,6 +239,8 @@ F:	cmd/armffa.c
 F:	drivers/arm-ffa/
 F:	include/arm_ffa.h
 F:	include/arm_ffa_helper.h
+F:	include/sandbox_arm_ffa.h
+F:	include/sandbox_arm_ffa_helper.h
 F:	lib/arm-ffa/
 
 ARM FREESCALE IMX
diff --git a/common/board_r.c b/common/board_r.c
index bb5f1d0aa6..a03b5254b7 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -775,7 +775,7 @@ static init_fnc_t init_sequence_r[] = {
 	INIT_FUNC_WATCHDOG_RESET
 	initr_net,
 #endif
-#ifdef CONFIG_ARM_FFA_TRANSPORT
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	ffa_helper_bus_discover,
 #endif
 #ifdef CONFIG_POST
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 4fbe148074..d6b3a137e3 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -252,3 +252,5 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_SANDBOX_FFA=y
\ No newline at end of file
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1826cf0195..161ff221bf 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -326,3 +326,5 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
+CONFIG_SANDBOX_FFA=y
\ No newline at end of file
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index f8804e1f41..7cb5ea307c 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -203,6 +203,7 @@ Supported Drivers
 
 U-Boot sandbox supports these emulations:
 
+- Arm FF-A
 - Block devices
 - Chrome OS EC
 - GPIO
diff --git a/drivers/arm-ffa/Kconfig b/drivers/arm-ffa/Kconfig
index fa2b2fecfb..5774ae6496 100644
--- a/drivers/arm-ffa/Kconfig
+++ b/drivers/arm-ffa/Kconfig
@@ -2,7 +2,7 @@
 
 config ARM_FFA_TRANSPORT
 	bool "Enable Arm Firmware Framework for Armv8-A driver"
-	depends on DM && ARM64
+	depends on DM && (ARM64 || SANDBOX)
 	select ARM_SMCCC if ARM64
 	select CMD_ARMFFA
 	select LIB_UUID
@@ -26,3 +26,9 @@ config ARM_FFA_TRANSPORT
 	  FF-A communication is handled by one device and one instance (the bus).
 	  This FF-A driver takes care of all the interactions between Normal world
 	  and Secure World.
+
+config SANDBOX_FFA
+	bool "FF-A Sandbox driver"
+	depends on ARM_FFA_TRANSPORT && SANDBOX
+	help
+	  This emulates the FF-A handling under Sandbox and allows to test the FF-A driver
diff --git a/drivers/arm-ffa/Makefile b/drivers/arm-ffa/Makefile
index 7bc9a336a9..df1cfe6ef0 100644
--- a/drivers/arm-ffa/Makefile
+++ b/drivers/arm-ffa/Makefile
@@ -4,3 +4,4 @@
 #
 
 obj-y += arm-ffa-uclass.o core.o
+obj-$(CONFIG_SANDBOX_FFA) += sandbox.o
diff --git a/drivers/arm-ffa/arm-ffa-uclass.c b/drivers/arm-ffa/arm-ffa-uclass.c
index 2439f87586..418aa06dd6 100644
--- a/drivers/arm-ffa/arm-ffa-uclass.c
+++ b/drivers/arm-ffa/arm-ffa-uclass.c
@@ -11,6 +11,10 @@
 #include <log.h>
 #include <asm/global_data.h>
 
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#include <sandbox_arm_ffa.h>
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 UCLASS_DRIVER(ffa) = {
@@ -42,16 +46,42 @@ int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *fu
 	return ffa_device_get_ops()->invoke_func(func_id, func_data);
 }
 
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+
+/**
+ * sandbox_ffa_get_invoke_func - performs a call to the Sandbox FF-A driver dispatcher
+ * @func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the query arguments
+ *				container structure.
+ *
+ * This function passes the FF-A function ID to be queried during sandbox test cases
+ *  and its arguments to the Sandbox FF-A driver dispatcher.
+ * This function is called by the Sandbox FF-A helper function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data)
+{
+	if (!sandbox_ffa_device_get_ops()->invoke_func)
+		return -EINVAL;
+
+	return sandbox_ffa_device_get_ops()->invoke_func(func_id, func_data);
+}
+#endif
+
 /**
- * ffa_bus_discover - discover FF-A bus and probe the arm_ffa device
+ * ffa_bus_discover - discover FF-A bus and probe arm_ffa and sandbox_arm_ffa devices
  *
  * This boot time function makes sure the FF-A bus is discoverable.
- * Then, the arm_ffa device is probed and ready to use.
+ * Then, the arm_ffa and sandbox_arm_ffa devices are ready to use.
+ *
  * This function is called automatically at initcalls
  * level (after u-boot relocation).
  *
  * Arm FF-A transport is implemented through arm_ffa u-boot device managing the FF-A
- * communication.
+ * communication. In Sandbox mode sandbox_arm_ffa is used to test arm_ffa driver.
  * All FF-A clients should use the arm_ffa device to use the FF-A transport.
  *
  * Return:
@@ -60,5 +90,14 @@ int __ffa_runtime ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *fu
  */
 int ffa_bus_discover(void)
 {
-	return ffa_get_device();
+	int ret;
+
+	ret = ffa_get_device();
+
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+	if (ret == FFA_ERR_STAT_SUCCESS)
+		ret = sandbox_ffa_get_device();
+#endif
+
+	return ret;
 }
diff --git a/drivers/arm-ffa/core.c b/drivers/arm-ffa/core.c
index 09e4eb753a..246abc1473 100644
--- a/drivers/arm-ffa/core.c
+++ b/drivers/arm-ffa/core.c
@@ -5,6 +5,11 @@
  */
 
 #include "arm_ffa_prv.h"
+
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#include "sandbox_arm_ffa_prv.h"
+#endif
+
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <common.h>
@@ -88,8 +93,10 @@ static int ffa_get_version(void)
 
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_VERSION;
 	a1 = FFA_VERSION_1_0;
@@ -132,8 +139,10 @@ static int ffa_get_endpoint_id(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_ID_GET;
 
@@ -206,8 +215,10 @@ static int ffa_get_rxtx_map_features(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_FEATURES;
 	a1 = FFA_RXTX_MAP;
@@ -433,8 +444,10 @@ static int ffa_map_rxtx_buffers(size_t buf_4k_pages)
 
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	ret = ffa_alloc_rxtx_buffers(buf_4k_pages);
 	if (ret != FFA_ERR_STAT_SUCCESS)
@@ -502,8 +515,10 @@ static int ffa_unmap_rxtx_buffers(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_RXTX_UNMAP;
 	a1 = PREP_SELF_ENDPOINT_ID(ffa_priv_data.id);
@@ -514,11 +529,12 @@ static int ffa_unmap_rxtx_buffers(void)
 	case FFA_ERROR:
 	{
 		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
-			panic("[FFA] FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
+			ffa_panic("FFA_RXTX_UNMAP is not implemented at this FF-A instance\n");
 		else if (((int)res.a2) == FFA_ERR_STAT_INVALID_PARAMETERS)
-			panic("[FFA] There is no buffer pair registered on behalf of the caller\n");
+			ffa_panic("There is no buffer pair registered on behalf of the caller\n");
 		else
-			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+			ffa_panic("Undefined error (%d)\n", ((int)res.a2));
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 	{
@@ -526,19 +542,24 @@ static int ffa_unmap_rxtx_buffers(void)
 		int ret;
 
 		ret = ffa_get_rxtx_buffers_pages_cnt(&buf_4k_pages);
-		if (ret != FFA_ERR_STAT_SUCCESS)
-			panic("[FFA] RX/TX buffers unmapped but failure in getting pages count\n");
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_panic("RX/TX buffers unmapped but failure in getting pages count\n");
+			return -ENODEV;
+		}
 
 		ret = ffa_free_rxtx_buffers(buf_4k_pages);
-		if (ret != FFA_ERR_STAT_SUCCESS)
-			panic("[FFA] RX/TX buffers unmapped but failure in freeing the memory\n");
+		if (ret != FFA_ERR_STAT_SUCCESS) {
+			ffa_panic("RX/TX buffers unmapped but failure in freeing the memory\n");
+			return -ENODEV;
+		}
 
 		ffa_info("RX/TX buffers unmapped and memory freed");
 
 		return FFA_ERR_STAT_SUCCESS;
 	}
 	default:
-		panic("[FFA] Undefined response function (0x%lx)", res.a0);
+		ffa_panic("Undefined response function (0x%lx)", res.a0);
+		return -ENODEV;
 	}
 }
 
@@ -556,8 +577,10 @@ static int ffa_release_rx_buffer(void)
 {
 	FFA_DECLARE_ARGS;
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_RX_RELEASE;
 
@@ -567,17 +590,19 @@ static int ffa_release_rx_buffer(void)
 	case FFA_ERROR:
 	{
 		if (((int)res.a2) == FFA_ERR_STAT_NOT_SUPPORTED)
-			panic("[FFA] FFA_RX_RELEASE is not implemented at this FF-A instance\n");
+			ffa_panic("FFA_RX_RELEASE is not implemented at this FF-A instance\n");
 		else if (((int)res.a2) == FFA_ERR_STAT_DENIED)
-			panic("[FFA] Caller did not have ownership of the RX buffer\n");
+			ffa_panic("Caller did not have ownership of the RX buffer\n");
 		else
-			panic("[FFA] Undefined error (%d)\n", ((int)res.a2));
+			ffa_panic("Undefined error (%d)\n", ((int)res.a2));
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 		return FFA_ERR_STAT_SUCCESS;
 
 	default:
-		panic("[FFA] Undefined response function (0x%lx)\n", res.a0);
+		ffa_panic("Undefined response function (0x%lx)\n", res.a0);
+		return -ENODEV;
 	}
 }
 
@@ -769,8 +794,10 @@ static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
 	unsigned long a7 = 0;
 	struct arm_smccc_res res = {0};
 
-	if (!ffa_priv_data.invoke_ffa_fn)
-		panic("[FFA] no private data found\n");
+	if (!ffa_priv_data.invoke_ffa_fn) {
+		ffa_panic("no private data found\n");
+		return -ENODEV;
+	}
 
 	a0 = FFA_PARTITION_INFO_GET;
 
@@ -846,7 +873,7 @@ static int ffa_query_partitions_info(union ffa_partition_uuid *part_uuid,
 		ret = ffa_release_rx_buffer();
 
 		if (!part_uuid && !res.a2) {
-			ffa_err("[FFA] no partition installed in the system");
+			ffa_err("no partition installed in the system");
 			return -ENODEV;
 		}
 
@@ -937,8 +964,10 @@ static int ffa_get_partitions_info(struct ffa_interface_data *func_data)
 		return -EINVAL;
 	}
 
-	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs)
-		panic("[FFA] No partition installed\n");
+	if (!ffa_priv_data.partitions.count || !ffa_priv_data.partitions.descs) {
+		ffa_panic("No partition installed\n");
+		return -ENODEV;
+	}
 
 	if (func_data->data0_size == sizeof(union ffa_partition_uuid) &&
 	    func_data->data0 &&
@@ -1176,6 +1205,7 @@ static int __ffa_runtime ffa_msg_send_direct_req(struct ffa_interface_data
 			/* Undefined error */
 			return -ENXIO;
 		}
+		return -ENODEV;
 	}
 	case FFA_SUCCESS:
 
@@ -1238,7 +1268,7 @@ int __ffa_runtime invoke_ffa_drv_api(u32 func_id,
 /**
  * ffa_set_conduit - Set the conduit
  *
- * This boot time function clears the private data structure and sets the conduit
+ * This boot time function sets the conduit
  *
  * Return:
  *
@@ -1248,7 +1278,12 @@ static int ffa_set_conduit(void)
 {
 	ffa_priv_data.conduit = FFA_CONDUIT_SMC;
 
-	ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+		ffa_priv_data.invoke_ffa_fn = sandbox_arm_ffa_smccc_smc;
+		ffa_info("Using SMC emulation");
+#else
+		ffa_priv_data.invoke_ffa_fn = arm_ffa_smccc_smc;
+#endif
 
 	ffa_info("Conduit is SMC");
 
diff --git a/drivers/arm-ffa/sandbox.c b/drivers/arm-ffa/sandbox.c
new file mode 100644
index 0000000000..d4a953fc3b
--- /dev/null
+++ b/drivers/arm-ffa/sandbox.c
@@ -0,0 +1,669 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
+ */
+
+#include "sandbox_arm_ffa_prv.h"
+#include <asm/global_data.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+#include <mapmem.h>
+#include <string.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * The device private data structure containing all the emulated secure world data
+ */
+static struct sandbox_ffa_prvdata  sandbox_ffa_priv_data = {0};
+
+/* The partitions (SPs) table */
+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
+	{
+		.info = { .id = 0x1245, .exec_ctxt = 0x5687, .properties = 0x89325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x9836, .exec_ctxt = 0x9587, .properties = 0x45325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x6452, .exec_ctxt = 0x7687, .properties = 0x23325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE1_UUID_DATA}}
+	},
+	{
+		.info = { .id = 0x7814, .exec_ctxt = 0x1487, .properties = 0x70325621 },
+		.UUID = { .bytes = {SANDBOX_SERVICE2_UUID_DATA}}
+	}
+
+};
+
+/*
+ * Driver functions
+ */
+
+/**
+ * sandbox_ffa_get_device - probes the sandbox_arm_ffa device
+ *
+ * This function makes sure the sandbox_arm_ffa device is probed
+ * This function makes sure the sandbox_arm_ffa device is
+ * created, bound to this driver, probed and ready to use.
+ *
+ * sandbox_arm_ffa depends on arm_ffa device. This dependency is
+ * handled by ffa_bus_discover function. arm_ffa is probed first then
+ * sandbox_arm_ffa.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_device(void)
+{
+	int ret;
+
+	if (sandbox_ffa_priv_data.dev)
+		return FFA_ERR_STAT_SUCCESS;
+
+	ret = device_bind(dm_root(),
+			  DM_DRIVER_GET(sandbox_arm_ffa),
+			  FFA_SANDBOX_DRV_NAME,
+			  NULL,
+			  ofnode_null(),
+			  &sandbox_ffa_priv_data.dev);
+	if (ret) {
+		sandbox_ffa_priv_data.dev = NULL;
+		return ret;
+	}
+
+	ret = device_probe(sandbox_ffa_priv_data.dev);
+	if (ret) {
+		ffa_err("[Sandbox] can not probe  the device");
+		device_unbind(sandbox_ffa_priv_data.dev);
+		sandbox_ffa_priv_data.dev = NULL;
+		return ret;
+	}
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_version - Emulated FFA_VERSION handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_VERSION FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_version)
+{
+	sandbox_ffa_priv_data.fwk_version = FFA_VERSION_1_0;
+	res->a0 = sandbox_ffa_priv_data.fwk_version;
+
+	/* w1-w7 MBZ */
+	memset(FFA_W1W7_MBZ_REG_START, 0, FFA_W1W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_id_get - Emulated FFA_ID_GET handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_ID_GET FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_id_get)
+{
+	res->a0 = FFA_SUCCESS;
+	res->a1 = 0;
+
+	sandbox_ffa_priv_data.id = NS_PHYS_ENDPOINT_ID;
+	res->a2 = sandbox_ffa_priv_data.id;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START, 0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_features - Emulated FFA_FEATURES handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_FEATURES FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_features)
+{
+	switch (a1) {
+	case FFA_RXTX_MAP:
+	{
+		res->a0 = FFA_SUCCESS;
+		res->a2 = RXTX_BUFFERS_MIN_SIZE;
+		res->a3 = 0;
+		/* w4-w7 MBZ */
+		memset(FFA_W4W7_MBZ_REG_START,
+		       0, FFA_W4W7_MBZ_CNT * sizeof(unsigned long));
+		break;
+	}
+	default:
+	{
+		res->a0 = FFA_ERROR;
+		res->a2 = FFA_ERR_STAT_NOT_SUPPORTED;
+		/* w3-w7 MBZ */
+		memset(FFA_W3_MBZ_REG_START,
+		       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+		ffa_err("[Sandbox] FF-A interface 0x%lx not implemented", a1);
+	}
+	}
+
+	res->a1 = 0;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_partition_info_get - Emulated FFA_PARTITION_INFO_GET handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_PARTITION_INFO_GET FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_partition_info_get)
+{
+	struct ffa_partition_info *rxbuf_desc_info = NULL;
+	u32 descs_cnt;
+	u32 descs_size_bytes;
+
+	res->a0 = FFA_ERROR;
+
+	if (!sandbox_ffa_priv_data.pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_DENIED;
+		goto cleanup;
+	}
+
+	if (sandbox_ffa_priv_data.pair_info.rxbuf_owned) {
+		res->a2 = FFA_ERR_STAT_BUSY;
+		goto cleanup;
+	}
+
+	if (!sandbox_ffa_priv_data.partitions.descs) {
+		sandbox_ffa_priv_data.partitions.descs = sandbox_partitions;
+		sandbox_ffa_priv_data.partitions.count = SANDBOX_PARTITIONS_CNT;
+	}
+
+	descs_size_bytes = SANDBOX_PARTITIONS_CNT * sizeof(struct ffa_partition_desc);
+
+	/* Abort if the RX buffer size is smaller than the descriptors buffer size */
+	if ((sandbox_ffa_priv_data.pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
+		res->a2 = FFA_ERR_STAT_NO_MEMORY;
+		goto cleanup;
+	}
+
+	rxbuf_desc_info = (struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf;
+
+	/* No UUID specified. Return the information of all partitions */
+	if (!a1 && !a2 && !a3 && !a4) {
+		for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+			*(rxbuf_desc_info++) =
+				sandbox_ffa_priv_data.partitions.descs[descs_cnt].info;
+
+		res->a0 = FFA_SUCCESS;
+		res->a2 = SANDBOX_PARTITIONS_CNT;
+		/* transfer ownership to the consumer: the non secure world */
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1;
+
+		goto cleanup;
+	}
+
+	/*
+	 * A UUID is specified. Return the information of all partitions matching
+	 * the UUID
+	 */
+
+	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+		if (a1 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a1 &&
+		    a2 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a2 &&
+		    a3 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a3 &&
+		    a4 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].UUID.words.a4) {
+			*(rxbuf_desc_info++) =
+				sandbox_ffa_priv_data.partitions.descs[descs_cnt].info;
+		}
+
+	if (rxbuf_desc_info != ((struct ffa_partition_info *)sandbox_ffa_priv_data.pair.rxbuf)) {
+		res->a0 = FFA_SUCCESS;
+		/* store the partitions count */
+		res->a2 = (unsigned long)
+			(rxbuf_desc_info - (struct ffa_partition_info *)
+			 sandbox_ffa_priv_data.pair.rxbuf);
+
+		/* transfer ownership to the consumer: the non secure world */
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 1;
+	} else {
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	}
+
+cleanup:
+
+	ffa_err("[Sandbox] FFA_PARTITION_INFO_GET (%ld)", res->a2);
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START, 0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rxtx_map - Emulated FFA_RXTX_MAP handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RXTX_MAP FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rxtx_map)
+{
+	res->a0 = FFA_ERROR;
+
+	if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) {
+		res->a2 = FFA_ERR_STAT_DENIED;
+		goto feedback;
+	}
+
+	if (a3 >= RXTX_BUFFERS_MIN_PAGES && a1 && a2) {
+		sandbox_ffa_priv_data.pair.txbuf = a1;
+		sandbox_ffa_priv_data.pair.rxbuf = a2;
+		sandbox_ffa_priv_data.pair_info.rxtx_buf_size = a3;
+		sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 1;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+		goto feedback;
+	}
+
+	if (!a1 || !a2)
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+	else
+		res->a2 = FFA_ERR_STAT_NO_MEMORY;
+
+	ffa_err("[Sandbox] error in FFA_RXTX_MAP arguments (%d)", (int)res->a2);
+
+feedback:
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rxtx_unmap - Emulated FFA_RXTX_UNMAP handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RXTX_UNMAP FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rxtx_unmap)
+{
+	res->a0 = FFA_ERROR;
+	res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+
+	if (GET_NS_PHYS_ENDPOINT_ID(a1) != sandbox_ffa_priv_data.id)
+		goto feedback;
+
+	if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) {
+		sandbox_ffa_priv_data.pair.txbuf = 0;
+		sandbox_ffa_priv_data.pair.rxbuf = 0;
+		sandbox_ffa_priv_data.pair_info.rxtx_buf_size = 0;
+		sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 0;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+		goto feedback;
+	}
+
+	ffa_err("[Sandbox] No buffer pair registered on behalf of the caller");
+
+feedback:
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_rx_release - Emulated FFA_RX_RELEASE handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_RX_RELEASE FF-A function.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_rx_release)
+{
+	if (!sandbox_ffa_priv_data.pair_info.rxbuf_owned) {
+		res->a0 = FFA_ERROR;
+		res->a2 = FFA_ERR_STAT_DENIED;
+	} else {
+		sandbox_ffa_priv_data.pair_info.rxbuf_owned = 0;
+		res->a0 = FFA_SUCCESS;
+		res->a2 = 0;
+	}
+
+	res->a1 = 0;
+
+	/* w3-w7 MBZ */
+	memset(FFA_W3_MBZ_REG_START,
+	       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_sp_valid - Checks SP validity
+ * @part_id: partition ID to check
+ *
+ * This is the function searches the input ID in the descriptors table.
+ *
+ * Return:
+ *
+ * 1 on success (Partition found). Otherwise, failure
+ */
+int sandbox_ffa_sp_valid(u16 part_id)
+{
+	u32 descs_cnt;
+
+	for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+		if (sandbox_ffa_priv_data.partitions.descs[descs_cnt].info.id == part_id)
+			return 1;
+
+	return 0;
+}
+
+/**
+ * sandbox_ffa_msg_send_direct_req - Emulated FFA_MSG_SEND_DIRECT_{REQ,RESP} handler function
+ * @{a0-a7} , res: The SMC call arguments and return structure.
+ *
+ * This is the function that emulates FFA_MSG_SEND_DIRECT_{REQ,RESP}
+ * FF-A functions.
+ *
+ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not supported.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
+{
+	u16 part_id;
+
+	part_id = GET_DST_SP_ID(a1);
+
+	if ((GET_NS_PHYS_ENDPOINT_ID(a1) != sandbox_ffa_priv_data.id) ||
+	    !sandbox_ffa_sp_valid(part_id) ||
+		a2) {
+		res->a0 = FFA_ERROR;
+		res->a1 = 0;
+		res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
+
+		/* w3-w7 MBZ */
+		memset(FFA_W3_MBZ_REG_START,
+		       0, FFA_W3W7_MBZ_CNT * sizeof(unsigned long));
+
+		return FFA_ERR_STAT_SUCCESS;
+	}
+
+	res->a0 = FFA_MSG_SEND_DIRECT_RESP;
+
+	res->a1 = PREP_SRC_SP_ID(part_id) |
+		PREP_NS_PHYS_ENDPOINT_ID(sandbox_ffa_priv_data.id);
+
+	res->a2 = 0;
+
+	/*
+	 * return 0xff bytes as a response
+	 */
+	res->a3 = 0xffffffff;
+	res->a4 = 0xffffffff;
+	res->a5 = 0xffffffff;
+	res->a6 = 0xffffffff;
+	res->a7 = 0xffffffff;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_get_prv_data - Returns the pointer to FF-A core pivate data
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * This is the handler that returns the address of the FF-A core pivate data.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_prv_data(struct ffa_interface_data *func_data)
+{
+	if (!func_data)
+		return -EINVAL;
+
+	if (!func_data->data0 || func_data->data0_size != sizeof(struct ffa_prvdata **))
+		return -EINVAL;
+
+	if (!func_data->data1 || func_data->data1_size != sizeof(struct sandbox_ffa_prvdata **))
+		return -EINVAL;
+
+	*((struct ffa_prvdata **)func_data->data0) = &ffa_priv_data;
+	*((struct sandbox_ffa_prvdata **)func_data->data1) = &sandbox_ffa_priv_data;
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_ffa_get_rxbuf_flags - Reading the mapping/ownership flags
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * This is the handler that queries the status flags of the following emulated ABIs:
+ * FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_get_rxbuf_flags(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	if (!func_data)
+		return -EINVAL;
+
+	if (!func_data->data0 || func_data->data0_size != sizeof(u8))
+		return -EINVAL;
+
+	switch (queried_func_id) {
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+		*((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_mapped;
+		return FFA_ERR_STAT_SUCCESS;
+	case FFA_RX_RELEASE:
+		*((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_owned;
+		return FFA_ERR_STAT_SUCCESS;
+	default:
+		ffa_err("[Sandbox] The querried  FF-A interface flag (%d) undefined",
+			queried_func_id);
+		return -EINVAL;
+	}
+}
+
+/**
+ * invoke_sandbox_ffa_drv_api - The driver dispatcher function
+ * @queried_func_id:	The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * The dispatcher function that selects the handler that queries the
+ * status of FF-A ABIs given in the input argument.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int invoke_sandbox_ffa_drv_api(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	switch (queried_func_id) {
+	case FFA_VERSION:
+	case FFA_ID_GET:
+	case FFA_FEATURES:
+		return sandbox_ffa_get_prv_data(func_data);
+	case FFA_RXTX_MAP:
+	case FFA_RXTX_UNMAP:
+	case FFA_RX_RELEASE:
+		return sandbox_ffa_get_rxbuf_flags(queried_func_id, func_data);
+	default:
+		ffa_err("[Sandbox] The querried  FF-A interface (%d) undefined", queried_func_id);
+		return -EINVAL;
+	}
+}
+
+/**
+ * sandbox_ffa_set_conduit - Set the conduit used by Sandbox
+ *
+ * Sets the conduit in the private data structure
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int sandbox_ffa_set_conduit(void)
+{
+	sandbox_ffa_priv_data.conduit = FFA_CONDUIT_SMC;
+
+	ffa_info("[Sandbox] Conduit is SMC");
+
+	return FFA_ERR_STAT_SUCCESS;
+}
+
+/**
+ * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation
+ * @dev:	the SMC arguments to be passed to the FF-A ABI
+ *
+ * Sandbox driver emulates the FF-A ABIs SMC call using this function.
+ * The emulated FF-A ABI is identified and invoked.
+ * FF-A emulation is based on the FF-A specification 1.0
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure.
+ * FF-A protocol error codes are returned using the registers arguments as described
+ * by the specification
+ */
+void sandbox_arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+			       unsigned long a2, unsigned long a3, unsigned long a4,
+			       unsigned long a5, unsigned long a6, unsigned long a7,
+			       struct arm_smccc_res *res)
+{
+	int ret = FFA_ERR_STAT_SUCCESS;
+
+	switch (a0) {
+	case FFA_VERSION:
+		ret = sandbox_ffa_version(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_PARTITION_INFO_GET:
+		ret = sandbox_ffa_partition_info_get(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RXTX_UNMAP:
+		ret = sandbox_ffa_rxtx_unmap(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_MSG_SEND_DIRECT_REQ:
+		ret = sandbox_ffa_msg_send_direct_req(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_ID_GET:
+		ret = sandbox_ffa_id_get(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_FEATURES:
+		ret = sandbox_ffa_features(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RXTX_MAP:
+		ret = sandbox_ffa_rxtx_map(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	case FFA_RX_RELEASE:
+		ret = sandbox_ffa_rx_release(a0, a1, a2, a3, a4, a5, a6, a7, res);
+		break;
+	default:
+		ffa_err("[Sandbox] Undefined FF-A interface (0x%x)", (unsigned int)a0);
+	}
+
+	if (ret != FFA_ERR_STAT_SUCCESS)
+		ffa_err("[Sandbox] FF-A ABI internal failure  (%d)", ret);
+}
+
+/**
+ * sandbox_ffa_probe - The driver probe function
+ * @dev:	the sandbox_arm_ffa device
+ *
+ * At probe level the conduit is set
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+static int sandbox_ffa_probe(struct udevice *dev)
+{
+	return sandbox_ffa_set_conduit();
+}
+
+/**
+ * sandbox_ffa_drv_ops - The driver operations  structure
+ * @invoke_func:	The driver dispatcher
+ */
+struct ffa_ops  sandbox_ffa_drv_ops = {
+	.invoke_func = invoke_sandbox_ffa_drv_api
+};
+
+/**
+ * sandbox_ffa_device_get_ops - driver operations getter
+ *
+ * Return:
+ * This function returns a pointer to the driver operations structure
+ */
+const struct ffa_ops *sandbox_ffa_device_get_ops(void)
+{
+	return &sandbox_ffa_drv_ops;
+}
+
+/**
+ * Declaring the sandbox_arm_ffa driver under UCLASS_FFA
+ */
+U_BOOT_DRIVER(sandbox_arm_ffa) = {
+	.name		= FFA_SANDBOX_DRV_NAME,
+	.id		= UCLASS_FFA,
+	.probe		= sandbox_ffa_probe,
+};
diff --git a/drivers/arm-ffa/sandbox_arm_ffa_prv.h b/drivers/arm-ffa/sandbox_arm_ffa_prv.h
new file mode 100644
index 0000000000..56b8d50a96
--- /dev/null
+++ b/drivers/arm-ffa/sandbox_arm_ffa_prv.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_PRV_H
+#define __SANDBOX_ARM_FFA_PRV_H
+
+#include "arm_ffa_prv.h"
+
+/*
+ * This header is private. It is exclusively used by the Sandbox FF-A driver
+ */
+
+/* FF-A core driver name */
+#define FFA_SANDBOX_DRV_NAME "sandbox_arm_ffa"
+
+/* Non-secure physical FF-A instance */
+#define NS_PHYS_ENDPOINT_ID (0)
+
+#define GET_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(31, 16)
+#define GET_NS_PHYS_ENDPOINT_ID(x)		\
+			((u16)(FIELD_GET(GET_NS_PHYS_ENDPOINT_ID_MASK, (x))))
+
+/* Helper macro for reading the destination partition ID */
+#define GET_DST_SP_ID_MASK		GENMASK(15, 0)
+#define GET_DST_SP_ID(x)		\
+			((u16)(FIELD_GET(GET_DST_SP_ID_MASK, (x))))
+
+/* Helper macro for setting the source partition ID */
+#define PREP_SRC_SP_ID_MASK		GENMASK(31, 16)
+#define PREP_SRC_SP_ID(x)		\
+			(FIELD_PREP(PREP_SRC_SP_ID_MASK, (x)))
+
+/* Helper macro for setting the destination endpoint ID */
+#define PREP_NS_PHYS_ENDPOINT_ID_MASK		GENMASK(15, 0)
+#define PREP_NS_PHYS_ENDPOINT_ID(x)		\
+			(FIELD_PREP(PREP_NS_PHYS_ENDPOINT_ID_MASK, (x)))
+
+/*  RX/TX buffers minimum size */
+#define RXTX_BUFFERS_MIN_SIZE (RXTX_4K)
+#define RXTX_BUFFERS_MIN_PAGES (1)
+
+/* MBZ registers info */
+
+/* w1-w7 MBZ */
+#define FFA_W1W7_MBZ_CNT (7)
+#define FFA_W1W7_MBZ_REG_START (&res->a1)
+
+/* w4-w7 MBZ */
+#define FFA_W4W7_MBZ_CNT (4)
+#define FFA_W4W7_MBZ_REG_START (&res->a4)
+
+/* w3-w7 MBZ */
+#define FFA_W3W7_MBZ_CNT (5)
+#define FFA_W3_MBZ_REG_START (&res->a3)
+
+/* secure partitions count */
+#define SANDBOX_PARTITIONS_CNT (4)
+
+/* service 1  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE1_UUID_DATA	\
+	0xed, 0x32, 0xd5, 0x33,	\
+	0x99, 0xe6, 0x42, 0x09,	\
+	0x9c, 0xc0, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0xa7
+
+/* service 2 UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE2_UUID_DATA	\
+	0xab, 0xcd, 0xd5, 0x33,	\
+	0x99, 0xe6, 0x42, 0x09,	\
+	0x9c, 0xc0, 0x2d, 0x72,	\
+	0xcd, 0xd9, 0x98, 0xa7
+
+/**
+ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
+ * @rxbuf_owned:	RX buffer ownership flag (the owner is non secure world: the consumer)
+ * @rxbuf_mapped:	RX buffer mapping flag
+ * @txbuf_owned	TX buffer ownership flag
+ * @txbuf_mapped:	TX buffer mapping flag
+ * @rxtx_buf_size:	RX/TX buffers size as set by the FF-A core driver
+ *
+ * Data structure hosting the ownership/mapping flags of the RX/TX buffers
+ * When a buffer is owned/mapped its corresponding flag is set to 1 otherwise 0.
+ */
+struct ffa_rxtxpair_info {
+	u8 rxbuf_owned;
+	u8 rxbuf_mapped;
+	u8 txbuf_owned;
+	u8 txbuf_mapped;
+	u32 rxtx_buf_size;
+};
+
+/**
+ * struct sandbox_ffa_prvdata - the driver private data structure
+ *
+ * @dev:	The arm_ffa device under u-boot driver model
+ * @fwk_version:	FF-A framework version
+ * @id:	u-boot endpoint ID
+ * @partitions:	The partitions descriptors structure
+ * @pair:	The RX/TX buffers pair
+ * @pair_info:	The RX/TX buffers pair flags and size
+ * @conduit:	The selected conduit
+ *
+ * The driver data structure hosting all the emulated secure world data.
+ */
+struct sandbox_ffa_prvdata {
+	struct udevice *dev;
+	u32 fwk_version;
+	u16 id;
+	struct ffa_partitions partitions;
+	struct ffa_rxtxpair pair;
+	struct ffa_rxtxpair_info pair_info;
+	enum ffa_conduit conduit;
+};
+
+void sandbox_arm_ffa_smccc_smc(unsigned long a0, unsigned long a1,
+			       unsigned long a2, unsigned long a3, unsigned long a4,
+			       unsigned long a5, unsigned long a6, unsigned long a7,
+			       struct arm_smccc_res *res);
+
+#define SANDBOX_SMC_FFA_ABI(ffabi) static int sandbox_##ffabi(unsigned long a0, unsigned long a1, \
+				    unsigned long a2, unsigned long a3, unsigned long a4, \
+				    unsigned long a5, unsigned long a6, unsigned long a7, \
+				    struct arm_smccc_res *res)
+
+/* The core FF-A private data structure to inspect */
+extern struct ffa_prvdata ffa_priv_data;
+
+#endif
diff --git a/include/arm_ffa.h b/include/arm_ffa.h
index 98db01ee72..c400de4a70 100644
--- a/include/arm_ffa.h
+++ b/include/arm_ffa.h
@@ -22,6 +22,13 @@
 #define ffa_info(fmt, ...)  pr_info("[FFA] " fmt "\n", ##__VA_ARGS__)
 #define ffa_err(fmt, ...)  pr_err("[FFA] " fmt "\n", ##__VA_ARGS__)
 
+/* panic only on real HW. On sandbox mode return an error code */
+#if CONFIG_IS_ENABLED(SANDBOX_FFA)
+#define ffa_panic(fmt, ...) ffa_err("[FFA] " fmt "\n", ##__VA_ARGS__)
+#else
+#define ffa_panic(fmt, ...) panic("[FFA] " fmt "\n", ##__VA_ARGS__)
+#endif
+
 /*
  * The driver operations success error code
  */
@@ -184,7 +191,7 @@ const struct ffa_ops * __ffa_runtime ffa_device_get_ops(void);
 int ffa_get_device(void);
 
 /**
- * ffa_bus_discover - discover FF-A bus and probes the arm_ffa device
+ * ffa_bus_discover - discover FF-A bus and probes the arm_ffa and sandbox_arm_ffa  devices
  */
 int ffa_bus_discover(void);
 #endif
diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h
new file mode 100644
index 0000000000..aa7a3454b9
--- /dev/null
+++ b/include/sandbox_arm_ffa.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_H
+#define __SANDBOX_ARM_FFA_H
+
+#include <arm_ffa.h>
+
+/**
+ * The device driver and the Uclass driver public functions
+ */
+
+/**
+ * sandbox_ffa_get_invoke_func - performs a call to the Sandbox FF-A driver dispatcher
+ */
+int sandbox_ffa_get_invoke_func(u32 func_id, struct ffa_interface_data *func_data);
+
+/**
+ * sandbox_ffa_device_get_ops - driver operations getter
+ */
+const struct ffa_ops *sandbox_ffa_device_get_ops(void);
+
+/**
+ * sandbox_ffa_get_device - create, bind and probe the sandbox_arm_ffa device
+ */
+int sandbox_ffa_get_device(void);
+
+#endif
diff --git a/include/sandbox_arm_ffa_helper.h b/include/sandbox_arm_ffa_helper.h
new file mode 100644
index 0000000000..f0fcd04536
--- /dev/null
+++ b/include/sandbox_arm_ffa_helper.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_HELPER_H
+#define __SANDBOX_ARM_FFA_HELPER_H
+
+#include <arm_ffa_helper.h>
+#include <sandbox_arm_ffa.h>
+#include "../drivers/arm-ffa/sandbox_arm_ffa_prv.h"
+
+/*
+ * This header is public. Including this header provides all FF-A Sandbox data structures
+ * It also provides the helper function allowing to pass data and invoke Sandbox  FF-A functions
+ * used for testing the FF-A core driver
+ */
+
+/**
+ * sandbox_ffa_helper_query_core_state - Wrapper function for
+ *  reading the FF-A core driver data
+ */
+int sandbox_ffa_helper_query_core_state(u32 queried_func_id, struct ffa_interface_data *func_data);
+
+#endif
diff --git a/lib/arm-ffa/Makefile b/lib/arm-ffa/Makefile
index cba625fde4..04159da8eb 100644
--- a/lib/arm-ffa/Makefile
+++ b/lib/arm-ffa/Makefile
@@ -6,3 +6,4 @@
 # This file only gets included when CONFIG_ARM_FFA_TRANSPORT_HELPERS is set
 
 obj-y += arm_ffa_helper.o
+obj-$(CONFIG_SANDBOX_FFA) += sandbox_arm_ffa_helper.o
diff --git a/lib/arm-ffa/arm_ffa_helper.c b/lib/arm-ffa/arm_ffa_helper.c
index a291b000a7..3ee6ee304f 100644
--- a/lib/arm-ffa/arm_ffa_helper.c
+++ b/lib/arm-ffa/arm_ffa_helper.c
@@ -108,7 +108,7 @@ int __ffa_runtime ffa_helper_msg_send_direct_req(struct ffa_interface_data
  * ffa_helper_bus_discover - Wrapper function for FF-A bus discovery
  *
  * This boot time function should be called to discover the FF-A bus and
- * probe the FF-A device.
+ * probe the arm_ffa and sandbox_arm_ffa devices.
  * To achieve that, this function is called automatically at initcalls
  * level (after u-boot relocation).
  *
diff --git a/lib/arm-ffa/sandbox_arm_ffa_helper.c b/lib/arm-ffa/sandbox_arm_ffa_helper.c
new file mode 100644
index 0000000000..7859f30fc7
--- /dev/null
+++ b/lib/arm-ffa/sandbox_arm_ffa_helper.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 ARM Limited
+ * Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
+ */
+
+#include <common.h>
+#include <sandbox_arm_ffa_helper.h>
+
+/**
+ * sandbox_ffa_helper_query_core_state - Wrapper function for querying FF-A implementation
+ *
+ * A helper function used for querying the status of FF-A ABIs given in the input argument
+ * and the FF-A core driver.
+ *
+ * Return:
+ *
+ * FFA_ERR_STAT_SUCCESS on success. Otherwise, failure
+ */
+int sandbox_ffa_helper_query_core_state(u32 queried_func_id, struct ffa_interface_data *func_data)
+{
+	return sandbox_ffa_get_invoke_func(queried_func_id, func_data);
+}
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index cffa2c69d6..12fc28fd82 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2118,7 +2118,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	struct efi_event *evt, *next_event;
 	efi_status_t ret = EFI_SUCCESS;
 
-#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	int ffa_ret;
 #endif
 
@@ -2182,7 +2182,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 	}
 
-#if defined(CONFIG_ARM_FFA_TRANSPORT)
+#if defined(CONFIG_ARM_FFA_TRANSPORT) && !defined(CONFIG_SANDBOX_FFA)
 	/* unmap FF-A RX/TX buffers */
 	ffa_ret = ffa_helper_unmap_rxtx_buffers();
 	if (ffa_ret)
-- 
2.17.1



More information about the U-Boot mailing list