Emulate Secure World's FF-A ABIs and allow testing U-Boot FF-A support

Features of the sandbox FF-A support:

- Introduce an FF-A emulator
- Introduce an FF-A device driver for FF-A comms with emulated Secure World
- Provides test methods allowing to read the status of the inspected ABIs

The sandbox FF-A emulator supports only 64-bit direct messaging.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
Cc: Tom Rini <tr...@konsulko.com>
Cc: Simon Glass <s...@chromium.org>
Cc: Ilias Apalodimas <ilias.apalodi...@linaro.org>
Cc: Jens Wiklander <jens.wiklan...@linaro.org>
Cc: Heinrich Schuchardt <xypron.g...@gmx.de>

---
Changelog:
===============

v10:

* split the FF-A sandbox support into an emulator and a driver
* read FFA_VERSION and FFA_PARTITION_INFO_GET state using
   sandbox_ffa_query_core_state()
* drop CONFIG_SANDBOX_FFA config
* address nits

v9: align FF-A sandbox driver with FF-A discovery through DM

v8: update ffa_bus_prvdata_get() to return a pointer rather than
    a pointer address

v7: state that sandbox driver supports only 64-bit direct messaging

v4: align sandbox driver with the new FF-A driver interfaces
    and new way of error handling

v1: introduce the sandbox driver

 MAINTAINERS                                   |   3 +-
 arch/sandbox/dts/sandbox.dtsi                 |   8 +
 arch/sandbox/dts/test.dts                     |   8 +
 arch/sandbox/include/asm/sandbox_arm_ffa.h    |  68 ++
 .../include/asm/sandbox_arm_ffa_priv.h        | 133 ++++
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 doc/arch/arm64.ffa.rst                        |   7 +-
 doc/arch/sandbox/sandbox.rst                  |   1 +
 drivers/firmware/arm-ffa/Kconfig              |  13 +-
 drivers/firmware/arm-ffa/Makefile             |  10 +-
 drivers/firmware/arm-ffa/ffa-emul-uclass.c    | 732 ++++++++++++++++++
 .../firmware/arm-ffa/sandbox_arm_ffa_priv.h   |  14 -
 drivers/firmware/arm-ffa/sandbox_ffa.c        | 108 +++
 include/dm/uclass-id.h                        |   1 +
 15 files changed, 1087 insertions(+), 21 deletions(-)
 create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa.h
 create mode 100644 arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
 create mode 100644 drivers/firmware/arm-ffa/ffa-emul-uclass.c
 delete mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
 create mode 100644 drivers/firmware/arm-ffa/sandbox_ffa.c

diff --git a/MAINTAINERS b/MAINTAINERS
index add208e4ef..b8019517ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,12 +269,13 @@ F:        configs/cortina_presidio-asic-pnand_defconfig
 ARM FF-A
 M:     Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
 S:     Maintained
+F:     arch/sandbox/include/asm/sandbox_arm_ffa.h
+F:     arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
 F:     cmd/armffa.c
 F:     doc/arch/arm64.ffa.rst
 F:     doc/usage/cmd/armffa.rst
 F:     drivers/firmware/arm-ffa/
 F:     include/arm_ffa.h
-F:     include/sandbox_arm_ffa.h
 
 ARM FREESCALE IMX
 M:     Stefano Babic <sba...@denx.de>
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 30a305c4d2..ac713800d1 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -445,6 +445,14 @@
        thermal {
                compatible = "sandbox,thermal";
        };
+
+       arm-ffa-emul {
+               compatible = "sandbox,arm-ffa-emul";
+       };
+
+       sandbox-arm-ffa {
+               compatible = "sandbox,arm-ffa";
+       };
 };
 
 &cros_ec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index d72d7a567a..bd42906159 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1802,6 +1802,14 @@
                compatible = "u-boot,fwu-mdata-gpt";
                fwu-mdata-store = <&mmc0>;
        };
+
+       arm-ffa-emul {
+               compatible = "sandbox,arm-ffa-emul";
+       };
+
+       sandbox-arm-ffa {
+               compatible = "sandbox,arm-ffa";
+       };
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa.h 
b/arch/sandbox/include/asm/sandbox_arm_ffa.h
new file mode 100644
index 0000000000..3652830e4e
--- /dev/null
+++ b/arch/sandbox/include/asm/sandbox_arm_ffa.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022-2023 Arm Limited and/or its affiliates 
<open-source-off...@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_H
+#define __SANDBOX_ARM_FFA_H
+
+#include <arm_ffa.h>
+
+/*
+ * This header provides public sandbox FF-A emulator declarations
+ * and declarations needed by FF-A sandbox clients
+ */
+
+/* UUIDs strings of the emulated services */
+#define SANDBOX_SERVICE1_UUID  "ed32d533-4209-99e6-2d72-cdd998a79cc0"
+#define SANDBOX_SERVICE2_UUID  "ed32d544-4209-99e6-2d72-cdd998a79cc0"
+
+/* IDs of the emulated secure partitions (SPs) */
+#define SANDBOX_SP1_ID 0x1245
+#define SANDBOX_SP2_ID 0x9836
+#define SANDBOX_SP3_ID 0x6452
+#define SANDBOX_SP4_ID 0x7814
+
+/* Invalid service UUID (no matching SP) */
+#define SANDBOX_SERVICE3_UUID  "55d532ed-0942-e699-722d-c09ca798d9cd"
+
+/* Invalid service UUID (invalid UUID string format) */
+#define SANDBOX_SERVICE4_UUID  "32ed-0942-e699-722d-c09ca798d9cd"
+
+/* Number of valid services */
+#define SANDBOX_SP_COUNT_PER_VALID_SERVICE     2
+
+/**
+ * struct ffa_sandbox_data - query ABI state data structure
+ * @data0_size:        size of the first argument
+ * @data0:     pointer to the first argument
+ * @data1_size>:       size of the second argument
+ * @data1:     pointer to the second argument
+ *
+ * Used to pass various types of data with different sizes between
+ * the test cases and the sandbox emulator.
+ * The data is for querying FF-A ABIs state.
+ */
+struct ffa_sandbox_data {
+       u32 data0_size; /* size of the first argument */
+       void *data0; /* pointer to the first argument */
+       u32 data1_size; /* size of the second argument */
+       void *data1; /* pointer to the second argument */
+};
+
+/* The sandbox FF-A  emulator public functions */
+
+/**
+ * sandbox_ffa_query_core_state() - Inspect the FF-A ABIs
+ * @queried_func_id:   The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int sandbox_ffa_query_core_state(u32 queried_func_id,
+                                struct ffa_sandbox_data *func_data);
+
+#endif
diff --git a/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h 
b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
new file mode 100644
index 0000000000..8fbfa3760d
--- /dev/null
+++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022-2023 Arm Limited and/or its affiliates 
<open-source-off...@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
+ */
+
+#ifndef __SANDBOX_ARM_FFA_PRV_H
+#define __SANDBOX_ARM_FFA_PRV_H
+
+#include <arm_ffa_priv.h>
+
+/* This header is exclusively used by the Sandbox FF-A driver and emulator */
+
+/* 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 */
+
+/* x1-x7 MBZ */
+#define FFA_X1X7_MBZ_CNT (7)
+#define FFA_X1X7_MBZ_REG_START (&res->a1)
+
+/* x4-x7 MBZ */
+#define FFA_X4X7_MBZ_CNT (4)
+#define FFA_X4X7_MBZ_REG_START (&res->a4)
+
+/* x3-x7 MBZ */
+#define FFA_X3X7_MBZ_CNT (5)
+#define FFA_X3_MBZ_REG_START (&res->a3)
+
+/* number of emulated FF-A secure partitions (SPs) */
+#define SANDBOX_PARTITIONS_CNT (4)
+
+/* Binary data of the emulated services UUIDs */
+
+/* service 1  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE1_UUID_A1       0xed32d533
+#define SANDBOX_SERVICE1_UUID_A2       0x99e64209
+#define SANDBOX_SERVICE1_UUID_A3       0x9cc02d72
+#define SANDBOX_SERVICE1_UUID_A4       0xcdd998a7
+
+/* service 2  UUID binary data (little-endian format) */
+#define SANDBOX_SERVICE2_UUID_A1       0xed32d544
+#define SANDBOX_SERVICE2_UUID_A2       0x99e64209
+#define SANDBOX_SERVICE2_UUID_A3       0x9cc02d72
+#define SANDBOX_SERVICE2_UUID_A4       0xcdd998a7
+
+/**
+ * struct ffa_rxtxpair_info - structure hosting the RX/TX buffers flags
+ * @rxbuf_owned:       RX buffer ownership flag (the owner is non secure world)
+ * @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
+ *
+ * Hosts 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_emul - emulator data
+ *
+ * @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
+ * @test_ffa_data:     The data of the FF-A bus under test
+ *
+ * Hosts all the emulated secure world data.
+ */
+struct sandbox_ffa_emul {
+       u32 fwk_version;
+       u16 id;
+       struct ffa_partitions partitions;
+       struct ffa_rxtxpair pair;
+       struct ffa_rxtxpair_info pair_info;
+};
+
+/**
+ * struct ffa_emul_ops - Operations for the FF-A emulator
+ * @invoke_ffa_fn:     callback for the emulated SMC call
+ *
+ * Provides all the operations supported by the FF-A emulator.
+ */
+struct ffa_emul_ops {
+       void (*invoke_ffa_fn)(ffa_value_t args, ffa_value_t *res);
+};
+
+#define ffa_emul_get_ops(dev)        ((struct ffa_emul_ops 
*)(dev)->driver->ops)
+
+/**
+ * ffa_emul_find() - Finds the FF-A emulator
+ * @dev:       the sandbox FF-A device (sandbox-arm-ffa)
+ * @emulp:     the FF-A emulator device (sandbox-ffa-emul)
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_emul_find(struct udevice *dev, struct udevice **emulp);
+
+#endif
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index b7737814af..89c17e4042 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -260,3 +260,4 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index ac1e8bbbef..26ef035877 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -337,3 +337,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_ARM_FFA_TRANSPORT=y
diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst
index 5fedb0c255..457a0e112e 100644
--- a/doc/arch/arm64.ffa.rst
+++ b/doc/arch/arm64.ffa.rst
@@ -33,7 +33,11 @@ Runtime support will be added in future developments.
 The U-Boot FF-A support provides the following parts:
 
 - A Uclass driver providing generic FF-A methods.
-- An Arm FF-A driver providing Arm specific methods and reusing the Uclass 
methods.
+- An Arm FF-A device driver providing Arm specific methods and reusing the 
Uclass methods.
+- A sandbox emulator for Arm FF-A, emulates the FF-A side of the Secure World 
and provides
+  FF-A ABIs inspection methods.
+- An FF-A sandbox device driver for FF-A communication with the emulated 
Secure World.
+  The driver leverages the FF-A Uclass to establish FF-A communication.
 
 FF-A and SMC specifications
 -------------------------------------------
@@ -69,6 +73,7 @@ CONFIG_ARM_FFA_TRANSPORT
     Enables the FF-A support. Turn this on if you want to use FF-A
     communication.
     When using an Arm 64-bit platform, the Arm FF-A driver will be used.
+    When using sandbox, the sandbox FF-A emulator and FF-A sandbox driver will 
be used.
 
 FF-A ABIs under the hood
 ---------------------------------------
diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst
index cd7f8a2cb0..c5df372e00 100644
--- a/doc/arch/sandbox/sandbox.rst
+++ b/doc/arch/sandbox/sandbox.rst
@@ -200,6 +200,7 @@ Supported Drivers
 
 U-Boot sandbox supports these emulations:
 
+- Arm FF-A
 - Block devices
 - Chrome OS EC
 - GPIO
diff --git a/drivers/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
index a7d5392859..d75f8b53fd 100644
--- a/drivers/firmware/arm-ffa/Kconfig
+++ b/drivers/firmware/arm-ffa/Kconfig
@@ -2,9 +2,9 @@
 
 config ARM_FFA_TRANSPORT
        bool "Enable Arm Firmware Framework for Armv8-A driver"
-       depends on DM && ARM64
-       select ARM_SMCCC
-       select ARM_SMCCC_FEATURES
+       depends on DM && (ARM64 || SANDBOX)
+       select ARM_SMCCC if !SANDBOX
+       select ARM_SMCCC_FEATURES if !SANDBOX
        imply CMD_ARMFFA
        select LIB_UUID
        select DEVRES
@@ -33,5 +33,10 @@ config ARM_FFA_TRANSPORT
          Generic FF-A methods are implemented in the Uclass (arm-ffa-uclass.c).
          Arm specific methods are implemented in the Arm driver (arm-ffa.c).
 
-         For more details about the FF-A support, please refer to 
doc/arch/arm64.ffa.rst
+         FF-A sandbox is provided to run FF-A under sandbox and allows to test 
the FF-A Uclass.
+         Sandbox support includes an emulator for Arm FF-A which emulates the 
FF-A side of
+         the Secure World and provides FF-A ABIs inspection methods 
(ffa-emul-uclass.c).
+         An FF-A sandbox driver is also provided for FF-A communication with 
the emulated
+         Secure World (sandbox_ffa.c).
 
+         For more details about the FF-A support, please refer to 
doc/arch/arm64.ffa.rst
diff --git a/drivers/firmware/arm-ffa/Makefile 
b/drivers/firmware/arm-ffa/Makefile
index 11b1766285..318123a7f4 100644
--- a/drivers/firmware/arm-ffa/Makefile
+++ b/drivers/firmware/arm-ffa/Makefile
@@ -5,4 +5,12 @@
 # Authors:
 #   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
 
-obj-y += arm-ffa-uclass.o arm-ffa.o
+# build the generic FF-A methods
+obj-y += arm-ffa-uclass.o
+ifeq ($(CONFIG_SANDBOX),y)
+# build the FF-A sandbox emulator and driver
+obj-y += ffa-emul-uclass.o sandbox_ffa.o
+else
+# build the Arm64 FF-A driver
+obj-y += arm-ffa.o
+endif
diff --git a/drivers/firmware/arm-ffa/ffa-emul-uclass.c 
b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
new file mode 100644
index 0000000000..ba4d3c9f3f
--- /dev/null
+++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c
@@ -0,0 +1,732 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022-2023 Arm Limited and/or its affiliates 
<open-source-off...@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
+ */
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <string.h>
+#include <asm/global_data.h>
+#include <asm/sandbox_arm_ffa.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+#include <linux/errno.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* The partitions (SPs) table */
+static struct ffa_partition_desc sandbox_partitions[SANDBOX_PARTITIONS_CNT] = {
+       {
+               .info = { .id = SANDBOX_SP1_ID, .exec_ctxt = 0x5687,
+                         .properties = 0x89325621 },
+               .sp_uuid = {
+                       .a1 = SANDBOX_SERVICE1_UUID_A1,
+                       .a2 = SANDBOX_SERVICE1_UUID_A2,
+                       .a3 = SANDBOX_SERVICE1_UUID_A3,
+                       .a4 = SANDBOX_SERVICE1_UUID_A4,
+               }
+       },
+       {
+               .info = { .id = SANDBOX_SP2_ID, .exec_ctxt = 0x9587,
+                         .properties = 0x45325621 },
+               .sp_uuid = {
+                       .a1 = SANDBOX_SERVICE2_UUID_A1,
+                       .a2 = SANDBOX_SERVICE2_UUID_A2,
+                       .a3 = SANDBOX_SERVICE2_UUID_A3,
+                       .a4 = SANDBOX_SERVICE2_UUID_A4,
+               }
+       },
+       {
+               .info = { .id = SANDBOX_SP3_ID, .exec_ctxt = 0x7687,
+                         .properties = 0x23325621 },
+               .sp_uuid = {
+                       .a1 = SANDBOX_SERVICE1_UUID_A1,
+                       .a2 = SANDBOX_SERVICE1_UUID_A2,
+                       .a3 = SANDBOX_SERVICE1_UUID_A3,
+                       .a4 = SANDBOX_SERVICE1_UUID_A4,
+               }
+       },
+       {
+               .info = { .id = SANDBOX_SP4_ID, .exec_ctxt = 0x1487,
+                         .properties = 0x70325621 },
+               .sp_uuid = {
+                       .a1 = SANDBOX_SERVICE2_UUID_A1,
+                       .a2 = SANDBOX_SERVICE2_UUID_A2,
+                       .a3 = SANDBOX_SERVICE2_UUID_A3,
+                       .a4 = SANDBOX_SERVICE2_UUID_A4,
+               }
+       }
+
+};
+
+/* The emulator functions */
+
+/**
+ * sandbox_ffa_version() - Emulated FFA_VERSION handler function
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_VERSION FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+
+static int sandbox_ffa_version(struct udevice *dev, ffa_value_t *pargs, 
ffa_value_t *res)
+{
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       priv->fwk_version = FFA_VERSION_1_0;
+       res->a0 = priv->fwk_version;
+
+       /* x1-x7 MBZ */
+       memset(FFA_X1X7_MBZ_REG_START, 0,
+              FFA_X1X7_MBZ_CNT * sizeof(ulong));
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_id_get() - Emulated FFA_ID_GET handler function
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_ID_GET FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_id_get(struct udevice *dev, ffa_value_t *pargs, 
ffa_value_t *res)
+{
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       res->a0 = FFA_SMC_32(FFA_SUCCESS);
+       res->a1 = 0;
+
+       priv->id = NS_PHYS_ENDPOINT_ID;
+       res->a2 = priv->id;
+
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START, 0,
+              FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_features() - Emulated FFA_FEATURES handler function
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_FEATURES FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_features(ffa_value_t *pargs, ffa_value_t *res)
+{
+       res->a1 = 0;
+
+       if (pargs->a1 == FFA_SMC_64(FFA_RXTX_MAP)) {
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               res->a2 = RXTX_BUFFERS_MIN_SIZE;
+               res->a3 = 0;
+               /* x4-x7 MBZ */
+               memset(FFA_X4X7_MBZ_REG_START,
+                      0, FFA_X4X7_MBZ_CNT * sizeof(ulong));
+               return 0;
+       }
+
+       res->a0 = FFA_SMC_32(FFA_ERROR);
+       res->a2 = -NOT_SUPPORTED;
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START,
+              0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+       log_err("[FFA][Sandbox][Emul] FF-A interface 0x%lx not implemented\n",
+               pargs->a1);
+
+       return ffa_to_std_errmap[NOT_SUPPORTED];
+}
+
+/**
+ * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_PARTITION_INFO_GET FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_partition_info_get(struct udevice *dev, ffa_value_t 
*pargs, ffa_value_t *res)
+{
+       struct ffa_partition_info *rxbuf_desc_info = NULL;
+       u32 descs_cnt;
+       u32 descs_size_bytes;
+       int ret;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       res->a0 = FFA_SMC_32(FFA_ERROR);
+
+       if (!priv->pair.rxbuf) {
+               res->a2 = -DENIED;
+               ret = ffa_to_std_errmap[DENIED];
+               goto cleanup;
+       }
+
+       if (priv->pair_info.rxbuf_owned) {
+               res->a2 = -BUSY;
+               ret = ffa_to_std_errmap[BUSY];
+               goto cleanup;
+       }
+
+       if (!priv->partitions.descs) {
+               priv->partitions.descs = sandbox_partitions;
+               priv->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 descs buffer size */
+       if ((priv->pair_info.rxtx_buf_size * SZ_4K) < descs_size_bytes) {
+               res->a2 = -NO_MEMORY;
+               ret = ffa_to_std_errmap[NO_MEMORY];
+               goto cleanup;
+       }
+
+       rxbuf_desc_info = priv->pair.rxbuf;
+
+       /* No UUID specified. Return the information of all partitions */
+       if (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->a4) {
+               for (descs_cnt = 0; descs_cnt < SANDBOX_PARTITIONS_CNT;
+                    descs_cnt++)
+                       *(rxbuf_desc_info++) =
+                               priv->partitions.descs[descs_cnt].info;
+
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               res->a2 = SANDBOX_PARTITIONS_CNT;
+               /* Transfer ownership to the consumer: the non secure world */
+               priv->pair_info.rxbuf_owned = 1;
+               ret = 0;
+
+               goto cleanup;
+       }
+
+       /* A UUID specified. Return the info of all SPs matching the UUID */
+
+       for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+               if (pargs->a1 == priv->partitions.descs[descs_cnt].sp_uuid.a1 &&
+                   pargs->a2 == priv->partitions.descs[descs_cnt].sp_uuid.a2 &&
+                   pargs->a3 == priv->partitions.descs[descs_cnt].sp_uuid.a3 &&
+                   pargs->a4 == priv->partitions.descs[descs_cnt].sp_uuid.a4) {
+                       *(rxbuf_desc_info++) =
+                               priv->partitions.descs[descs_cnt].info;
+               }
+
+       if (rxbuf_desc_info != priv->pair.rxbuf) {
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               /* Store the partitions count */
+               res->a2 = (ulong)
+                       (rxbuf_desc_info - (struct ffa_partition_info *)
+                        priv->pair.rxbuf);
+               ret = 0;
+
+               /* Transfer ownership to the consumer: the non secure world */
+               priv->pair_info.rxbuf_owned = 1;
+       } else {
+               /* Unrecognized UUID */
+               res->a2 = -INVALID_PARAMETERS;
+               ret = ffa_to_std_errmap[INVALID_PARAMETERS];
+       }
+
+cleanup:
+
+       log_err("[FFA][Sandbox][Emul] FFA_PARTITION_INFO_GET (%ld)\n", res->a2);
+
+       res->a1 = 0;
+
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START, 0,
+              FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+       return ret;
+}
+
+/**
+ * sandbox_ffa_rxtx_map() - Emulated FFA_RXTX_MAP handler
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_RXTX_MAP FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_rxtx_map(struct udevice *dev, ffa_value_t *pargs, 
ffa_value_t *res)
+{
+       int ret;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       res->a0 = FFA_SMC_32(FFA_ERROR);
+
+       if (priv->pair.txbuf && priv->pair.rxbuf) {
+               res->a2 = -DENIED;
+               ret = ffa_to_std_errmap[DENIED];
+               goto feedback;
+       }
+
+       if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) {
+               priv->pair.txbuf = map_sysmem(pargs->a1, 0);
+               priv->pair.rxbuf = map_sysmem(pargs->a2, 0);
+               priv->pair_info.rxtx_buf_size = pargs->a3;
+               priv->pair_info.rxbuf_mapped = 1;
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               res->a2 = 0;
+               ret = 0;
+               goto feedback;
+       }
+
+       if (!pargs->a1 || !pargs->a2) {
+               res->a2 = -INVALID_PARAMETERS;
+               ret = ffa_to_std_errmap[INVALID_PARAMETERS];
+       } else {
+               res->a2 = -NO_MEMORY;
+               ret = ffa_to_std_errmap[NO_MEMORY];
+       }
+
+       log_err("[FFA][Sandbox][Emul] error in FFA_RXTX_MAP arguments (%d)\n",
+               (int)res->a2);
+
+feedback:
+
+       res->a1 = 0;
+
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START,
+              0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+       return ret;
+}
+
+/**
+ * sandbox_ffa_rxtx_unmap() - Emulated FFA_RXTX_UNMAP handler
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_RXTX_UNMAP FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_rxtx_unmap(struct udevice *dev, ffa_value_t *pargs, 
ffa_value_t *res)
+{
+       int ret;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       res->a0 = FFA_SMC_32(FFA_ERROR);
+       res->a2 = -INVALID_PARAMETERS;
+       ret = ffa_to_std_errmap[INVALID_PARAMETERS];
+
+       if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id)
+               goto feedback;
+
+       if (priv->pair.txbuf && priv->pair.rxbuf) {
+               priv->pair.txbuf = 0;
+               priv->pair.rxbuf = 0;
+               priv->pair_info.rxtx_buf_size = 0;
+               priv->pair_info.rxbuf_mapped = 0;
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               res->a2 = 0;
+               ret = 0;
+               goto feedback;
+       }
+
+       log_err("[FFA][Sandbox][Emul] No buffer pair registered on behalf of 
the caller\n");
+
+feedback:
+
+       res->a1 = 0;
+
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START,
+              0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+       return ret;
+}
+
+/**
+ * sandbox_ffa_rx_release() - Emulated FFA_RX_RELEASE handler
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_RX_RELEASE FF-A function.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_rx_release(struct udevice *dev, ffa_value_t *pargs, 
ffa_value_t *res)
+{
+       int ret;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       if (!priv->pair_info.rxbuf_owned) {
+               res->a0 = FFA_SMC_32(FFA_ERROR);
+               res->a2 = -DENIED;
+               ret = ffa_to_std_errmap[DENIED];
+       } else {
+               priv->pair_info.rxbuf_owned = 0;
+               res->a0 = FFA_SMC_32(FFA_SUCCESS);
+               res->a2 = 0;
+               ret = 0;
+       }
+
+       res->a1 = 0;
+
+       /* x3-x7 MBZ */
+       memset(FFA_X3_MBZ_REG_START,
+              0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+       return ret;
+}
+
+/**
+ * sandbox_ffa_sp_valid() - Checks SP validity
+ * @dev: The sandbox FF-A emulator device
+ * @part_id:   partition ID to check
+ *
+ * Searches the input ID in the descriptors table.
+ *
+ * Return:
+ *
+ * 1 on success (Partition found). Otherwise, failure
+ */
+static int sandbox_ffa_sp_valid(struct udevice *dev, u16 part_id)
+{
+       u32 descs_cnt;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       for (descs_cnt = 0 ; descs_cnt < SANDBOX_PARTITIONS_CNT ; descs_cnt++)
+               if (priv->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
+ * @dev: The sandbox FF-A emulator device
+ * @pargs: The SMC call input arguments a0-a7
+ * @res:  The SMC return data
+ *
+ * Emulates FFA_MSG_SEND_DIRECT_{REQ,RESP} FF-A ABIs.
+ * Only SMC 64-bit is supported in Sandbox.
+ *
+ * Emulating interrupts is not supported. So, FFA_RUN and FFA_INTERRUPT are not
+ * supported. In case of success FFA_MSG_SEND_DIRECT_RESP is returned with
+ * default pattern data (0xff).
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_msg_send_direct_req(struct udevice *dev,
+                                          ffa_value_t *pargs, ffa_value_t *res)
+{
+       u16 part_id;
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       part_id = GET_DST_SP_ID(pargs->a1);
+
+       if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id ||
+           !sandbox_ffa_sp_valid(dev, part_id) || pargs->a2) {
+               res->a0 = FFA_SMC_32(FFA_ERROR);
+               res->a1 = 0;
+               res->a2 = -INVALID_PARAMETERS;
+
+               /* x3-x7 MBZ */
+               memset(FFA_X3_MBZ_REG_START,
+                      0, FFA_X3X7_MBZ_CNT * sizeof(ulong));
+
+               return ffa_to_std_errmap[INVALID_PARAMETERS];
+       }
+
+       res->a0 = FFA_SMC_64(FFA_MSG_SEND_DIRECT_RESP);
+
+       res->a1 = PREP_SRC_SP_ID(part_id) |
+               PREP_NS_PHYS_ENDPOINT_ID(priv->id);
+
+       res->a2 = 0;
+
+       /* Return 0xff bytes as a response */
+       res->a3 = -1UL;
+       res->a4 = -1UL;
+       res->a5 = -1UL;
+       res->a6 = -1UL;
+       res->a7 = -1UL;
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_get_rxbuf_flags() - Reading the mapping/ownership flags
+ * @dev: The sandbox FF-A emulator device
+ * @queried_func_id:   The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * Queries the status flags of the following emulated
+ * ABIs: FFA_RXTX_MAP, FFA_RXTX_UNMAP, FFA_RX_RELEASE.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_get_rxbuf_flags(struct udevice *dev, u32 
queried_func_id,
+                                      struct ffa_sandbox_data *func_data)
+{
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       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) = priv->pair_info.rxbuf_mapped;
+               return 0;
+       case FFA_RX_RELEASE:
+               *((u8 *)func_data->data0) = priv->pair_info.rxbuf_owned;
+               return 0;
+       default:
+               log_err("[FFA][Sandbox][Emul] The querried FF-A interface flag 
(%d) undefined\n",
+                       queried_func_id);
+               return -EINVAL;
+       }
+}
+
+/**
+ * sandbox_ffa_get_fwk_version() - Return the FFA framework version
+ * @dev: The sandbox FF-A emulator device
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * Return the FFA framework version read from the FF-A emulator data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_get_fwk_version(struct udevice *dev, struct 
ffa_sandbox_data *func_data)
+{
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       if (!func_data)
+               return -EINVAL;
+
+       if (!func_data->data0 ||
+           func_data->data0_size != sizeof(priv->fwk_version))
+               return -EINVAL;
+
+       *((u32 *)func_data->data0) = priv->fwk_version;
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_get_parts() - Return the address of partitions data
+ * @dev: The sandbox FF-A emulator device
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * Return the address of partitions data read from the FF-A emulator data.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_get_parts(struct udevice *dev, struct ffa_sandbox_data 
*func_data)
+{
+       struct sandbox_ffa_emul *priv = dev_get_priv(dev);
+
+       if (!func_data)
+               return -EINVAL;
+
+       if (!func_data->data0 ||
+           func_data->data0_size != sizeof(struct ffa_partitions *))
+               return -EINVAL;
+
+       *((struct ffa_partitions **)func_data->data0) = &priv->partitions;
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_query_core_state() - Inspect the FF-A ABIs
+ * @queried_func_id:   The FF-A function to be queried
+ * @func_data:  Pointer to the FF-A function arguments container structure
+ *
+ * Queries the status of FF-A ABI specified in the input argument.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int sandbox_ffa_query_core_state(u32 queried_func_id,
+                                struct ffa_sandbox_data *func_data)
+{
+       struct udevice *dev;
+
+       uclass_first_device(UCLASS_FFA_EMUL, &dev);
+       if (!dev) {
+               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator during 
querying state\n");
+               return -ENODEV;
+       }
+
+       switch (queried_func_id) {
+       case FFA_RXTX_MAP:
+       case FFA_RXTX_UNMAP:
+       case FFA_RX_RELEASE:
+               return sandbox_ffa_get_rxbuf_flags(dev, queried_func_id, 
func_data);
+       case FFA_VERSION:
+               return sandbox_ffa_get_fwk_version(dev, func_data);
+       case FFA_PARTITION_INFO_GET:
+               return sandbox_ffa_get_parts(dev, func_data);
+       default:
+               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface (%d)\n",
+                       queried_func_id);
+               return -EINVAL;
+       }
+}
+
+/**
+ * sandbox_arm_ffa_smccc_smc() - FF-A SMC call emulation
+ * @args:      the SMC call arguments
+ * @res:       the SMC call returned data
+ *
+ * Emulates the FF-A ABIs SMC call.
+ * The emulated FF-A ABI is identified and invoked.
+ * FF-A emulation is based on the FF-A specification 1.0
+ *
+ * Return:
+ *
+ * 0 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(ffa_value_t args, ffa_value_t *res)
+{
+       int ret = 0;
+       struct udevice *dev;
+
+       uclass_first_device(UCLASS_FFA_EMUL, &dev);
+       if (!dev) {
+               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator during 
SMC emulation\n");
+               return;
+       }
+
+       switch (args.a0) {
+       case FFA_SMC_32(FFA_VERSION):
+               ret = sandbox_ffa_version(dev, &args, res);
+               break;
+       case FFA_SMC_32(FFA_PARTITION_INFO_GET):
+               ret = sandbox_ffa_partition_info_get(dev, &args, res);
+               break;
+       case FFA_SMC_32(FFA_RXTX_UNMAP):
+               ret = sandbox_ffa_rxtx_unmap(dev, &args, res);
+               break;
+       case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
+               ret = sandbox_ffa_msg_send_direct_req(dev, &args, res);
+               break;
+       case FFA_SMC_32(FFA_ID_GET):
+               ret = sandbox_ffa_id_get(dev, &args, res);
+               break;
+       case FFA_SMC_32(FFA_FEATURES):
+               ret = sandbox_ffa_features(&args, res);
+               break;
+       case FFA_SMC_64(FFA_RXTX_MAP):
+               ret = sandbox_ffa_rxtx_map(dev, &args, res);
+               break;
+       case FFA_SMC_32(FFA_RX_RELEASE):
+               ret = sandbox_ffa_rx_release(dev, &args, res);
+               break;
+       default:
+               log_err("[FFA][Sandbox][Emul] Undefined FF-A interface 
(0x%lx)\n",
+                       args.a0);
+       }
+
+       if (ret != 0)
+               log_err("[FFA][Sandbox][Emul] FF-A ABI internal failure 
(%d)\n", ret);
+}
+
+/**
+ * ffa_emul_find() - Finds the FF-A emulator
+ * @dev:       the sandbox FF-A device (sandbox-arm-ffa)
+ * @emulp:     the FF-A emulator device (sandbox-ffa-emul)
+ *
+ * Searches for the FF-A emulator and returns its device pointer.
+ *
+ * Return:
+ * 0 on success. Otherwise, failure
+ */
+int ffa_emul_find(struct udevice *dev, struct udevice **emulp)
+{
+       if (!emulp)
+               return -EINVAL;
+
+       *emulp = NULL;
+
+       uclass_first_device(UCLASS_FFA_EMUL, emulp);
+       if (!(*emulp)) {
+               log_err("[FFA][SANDBOX][Emul] Cannot find FF-A emulator\n");
+               return -ENODEV;
+       }
+
+       log_info("[FFA][Sandbox][Emul] FF-A emulator found\n");
+
+       return 0;
+}
+
+UCLASS_DRIVER(ffa_emul) = {
+       .name           = "ffa_emul",
+       .id             = UCLASS_FFA_EMUL,
+};
+
+/* Sandbox Arm FF-A emulator operations */
+
+static const struct ffa_emul_ops sandbox_ffa_emul_ops = {
+       .invoke_ffa_fn = sandbox_arm_ffa_smccc_smc,
+};
+
+static const struct udevice_id sandbox_ffa_emul_ids[] = {
+       { .compatible = "sandbox,arm-ffa-emul" },
+       { }
+};
+
+/* Declaring the sandbox FF-A emulator under UCLASS_FFA_EMUL */
+U_BOOT_DRIVER(sandbox_ffa_emul) = {
+       .name           = "sandbox_ffa_emul",
+       .id             = UCLASS_FFA_EMUL,
+       .of_match       = sandbox_ffa_emul_ids,
+       .ops            = &sandbox_ffa_emul_ops,
+       .priv_auto      = sizeof(struct sandbox_ffa_emul),
+};
diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h 
b/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
deleted file mode 100644
index 4338f9c9b1..0000000000
--- a/drivers/firmware/arm-ffa/sandbox_arm_ffa_priv.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright 2022-2023 Arm Limited and/or its affiliates 
<open-source-off...@arm.com>
- *
- * Authors:
- *   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
- */
-
-#ifndef __SANDBOX_ARM_FFA_PRV_H
-#define __SANDBOX_ARM_FFA_PRV_H
-
-/* Future sandbox support private declarations */
-
-#endif
diff --git a/drivers/firmware/arm-ffa/sandbox_ffa.c 
b/drivers/firmware/arm-ffa/sandbox_ffa.c
new file mode 100644
index 0000000000..bb150fd5cd
--- /dev/null
+++ b/drivers/firmware/arm-ffa/sandbox_ffa.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022-2023 Arm Limited and/or its affiliates 
<open-source-off...@arm.com>
+ *
+ * Authors:
+ *   Abdellatif El Khlifi <abdellatif.elkhl...@arm.com>
+ */
+#include <common.h>
+#include <arm_ffa.h>
+#include <dm.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <asm/sandbox_arm_ffa_priv.h>
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * ffa_set_smc_conduit() - Set the SMC conduit
+ *
+ * Selects the SMC conduit by setting the FF-A ABI invoke function.
+ * The function emulating the SMC call is provided by the FF-A emulator.
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+int ffa_set_smc_conduit(void)
+{
+       struct udevice *emul;
+       int ret;
+
+       ret = ffa_emul_find(NULL, &emul);
+       if (ret) {
+               log_err("[FFA][Sandbox] Cannot find FF-A emulator, SMC 
emulation failure\n");
+               return -ENODEV;
+       }
+
+       if (!ffa_emul_get_ops(emul)->invoke_ffa_fn) {
+               log_err("[FFA][Sandbox] Cannot get FF-A emulator ops, SMC 
emulation failure\n");
+               return -ENOSYS;
+       }
+
+       dscvry_info.invoke_ffa_fn = ffa_emul_get_ops(emul)->invoke_ffa_fn;
+       log_info("[FFA][Sandbox] Using emulated Arm SMC for FF-A conduit\n");
+
+       return 0;
+}
+
+/**
+ * sandbox_ffa_probe() - The sandbox FF-A driver probe function
+ * @dev:       the sandbox Arm FF-A bus device (sandbox-arm-ffa)
+ *
+ * Probing is done through ffa_do_probe()
+ *
+ * Return:
+ *
+ * 0 on success. Otherwise, failure
+ */
+static int sandbox_ffa_probe(struct udevice *dev)
+{
+       return ffa_do_probe(dev);
+}
+
+/**
+ * sandbox_ffa_bind() - The sandbox FF-A driver bind function
+ * @dev:       the sandbox-arm-ffa device
+ * Tries to discover the emulated FF-A bus.
+ * Return:
+ *
+ * 0 on success.
+ */
+static int sandbox_ffa_bind(struct udevice *dev)
+{
+       bool ret;
+
+       log_info("[FFA][Sandbox] binding the device\n");
+
+       ret = ffa_try_discovery();
+       if (ret)
+               return 0;
+       else
+               return -ENODEV;
+}
+
+/* Sandbox Arm FF-A emulator operations */
+
+static const struct ffa_bus_ops sandbox_ffa_ops = {
+       .partition_info_get = ffa_get_partitions_info_hdlr,
+       .sync_send_receive = ffa_msg_send_direct_req_hdlr,
+       .rxtx_unmap = ffa_unmap_rxtx_buffers_hdlr,
+};
+
+static const struct udevice_id sandbox_ffa_id[] = {
+       { "sandbox,arm-ffa", 0 },
+       { },
+};
+
+/* Declaring the sandbox FF-A driver under UCLASS_FFA */
+U_BOOT_DRIVER(sandbox_arm_ffa) = {
+       .name           = "sandbox_arm_ffa",
+       .of_match = sandbox_ffa_id,
+       .id             = UCLASS_FFA,
+       .probe          = sandbox_ffa_probe,
+       .bind           = sandbox_ffa_bind,
+       .ops            = &sandbox_ffa_ops,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index df77c7da58..4658411935 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -61,6 +61,7 @@ enum uclass_id {
        UCLASS_ETH,             /* Ethernet device */
        UCLASS_ETH_PHY,         /* Ethernet PHY device */
        UCLASS_FFA,             /* Arm Firmware Framework for Armv8-A */
+       UCLASS_FFA_EMUL,                /* sandbox FF-A device emulator */
        UCLASS_FIRMWARE,        /* Firmware */
        UCLASS_FPGA,            /* FPGA device */
        UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
-- 
2.25.1


Reply via email to