summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch')
-rw-r--r--meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch1185
1 files changed, 1185 insertions, 0 deletions
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch
new file mode 100644
index 0000000000..739f7810c1
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0011-arm_ffa-introduce-the-FF-A-Sandbox-driver.patch
@@ -0,0 +1,1185 @@
+From 553b57e39808ef04bc6aa54e0324f92b0175e476 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Mon, 6 Jun 2022 12:55:08 +0100
+Subject: [PATCH 11/26] arm_ffa: introduce the FF-A Sandbox driver
+
+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@arm.com>
+Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20220926101723.9965-1-abdellatif.elkhlifi@arm.com/]
+---
+
+Changelog:
+===============
+
+v4: align sandbox driver with the new FF-A driver interfaces
+ and new way of error handling
+
+v1: introduce the sandbox driver
+
+ MAINTAINERS | 1 +
+ common/board_r.c | 2 +-
+ configs/sandbox64_defconfig | 2 +
+ configs/sandbox_defconfig | 2 +
+ doc/arch/sandbox.rst | 1 +
+ drivers/firmware/arm-ffa/Kconfig | 10 +-
+ drivers/firmware/arm-ffa/Makefile | 1 +
+ drivers/firmware/arm-ffa/arm_ffa_prv.h | 15 +-
+ drivers/firmware/arm-ffa/core.c | 24 +-
+ drivers/firmware/arm-ffa/sandbox.c | 659 ++++++++++++++++++
+ .../firmware/arm-ffa/sandbox_arm_ffa_prv.h | 144 ++++
+ include/arm_ffa.h | 2 +-
+ include/sandbox_arm_ffa.h | 91 +++
+ lib/efi_loader/efi_boottime.c | 2 +-
+ 14 files changed, 941 insertions(+), 15 deletions(-)
+ create mode 100644 drivers/firmware/arm-ffa/sandbox.c
+ create mode 100644 drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h
+ create mode 100644 include/sandbox_arm_ffa.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 9f0a1b7387..96157db6b6 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -251,6 +251,7 @@ F: cmd/armffa.c
+ F: doc/README.ffa.drv
+ F: drivers/firmware/arm-ffa/
+ F: include/arm_ffa.h
++F: include/sandbox_arm_ffa.h
+
+ ARM FREESCALE IMX
+ M: Stefano Babic <sbabic@denx.de>
+diff --git a/common/board_r.c b/common/board_r.c
+index c75634286b..f838cd5958 100644
+--- a/common/board_r.c
++++ b/common/board_r.c
+@@ -783,7 +783,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_bus_discover,
+ #endif
+ #ifdef CONFIG_POST
+diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
+index d7f22b39ae..78bc5aaa96 100644
+--- a/configs/sandbox64_defconfig
++++ b/configs/sandbox64_defconfig
+@@ -250,3 +250,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 c509a924e6..8942aa7157 100644
+--- a/configs/sandbox_defconfig
++++ b/configs/sandbox_defconfig
+@@ -327,3 +327,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 068d4a3be4..5d7e1b2c48 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/firmware/arm-ffa/Kconfig b/drivers/firmware/arm-ffa/Kconfig
+index 40b467b0a5..263481de96 100644
+--- a/drivers/firmware/arm-ffa/Kconfig
++++ b/drivers/firmware/arm-ffa/Kconfig
+@@ -2,8 +2,8 @@
+
+ config ARM_FFA_TRANSPORT
+ bool "Enable Arm Firmware Framework for Armv8-A driver"
+- depends on DM && ARM64
+- select ARM_SMCCC
++ depends on DM && (ARM64 || SANDBOX)
++ select ARM_SMCCC if !SANDBOX
+ select CMD_ARMFFA
+ select LIB_UUID
+ select DEVRES
+@@ -38,3 +38,9 @@ config ARM_FFA_EFI_RUNTIME_MODE
+ The driver Code needed at runtime is placed at EFI runtime code section.
+ Turning this on makes ffa_copy_runtime_data available for use and the driver
+ code placed at EFI runtime code section.
++
++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/firmware/arm-ffa/Makefile b/drivers/firmware/arm-ffa/Makefile
+index 0b9b0a61b4..d50060b836 100644
+--- a/drivers/firmware/arm-ffa/Makefile
++++ b/drivers/firmware/arm-ffa/Makefile
+@@ -5,3 +5,4 @@
+
+ obj-y += arm-ffa-uclass.o core.o
+ obj-$(CONFIG_ARM_FFA_EFI_RUNTIME_MODE) += efi_ffa_runtime_data_mgr.o
++obj-$(CONFIG_SANDBOX_FFA) += sandbox.o
+diff --git a/drivers/firmware/arm-ffa/arm_ffa_prv.h b/drivers/firmware/arm-ffa/arm_ffa_prv.h
+index 7bc90f7f66..3e0d4c112c 100644
+--- a/drivers/firmware/arm-ffa/arm_ffa_prv.h
++++ b/drivers/firmware/arm-ffa/arm_ffa_prv.h
+@@ -19,6 +19,16 @@
+ /* FF-A core driver name */
+ #define FFA_DRV_NAME "arm_ffa"
+
++/* The FF-A SMC function definitions */
++
++#if CONFIG_IS_ENABLED(SANDBOX_FFA)
++#include "sandbox_arm_ffa.h"
++#else
++typedef struct arm_smccc_1_2_regs ffa_value_t;
++#endif
++
++typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res);
++
+ /* FF-A driver version definitions */
+
+ #define MAJOR_VERSION_MASK GENMASK(30, 16)
+@@ -94,11 +104,6 @@ struct ffa_abi_errmap {
+ #define FFA_ERRMAP_COUNT (FFA_LAST_ID - FFA_FIRST_ID + 1)
+ #define FFA_ID_TO_ERRMAP_ID(ffa_id) ((ffa_id) - FFA_FIRST_ID)
+
+-/* The FF-A SMC function definitions */
+-
+-typedef struct arm_smccc_1_2_regs ffa_value_t;
+-typedef void (*invoke_ffa_fn_t)(ffa_value_t args, ffa_value_t *res);
+-
+ /*
+ * struct ffa_partition_uuid - 16 bytes UUID transmitted by FFA_PARTITION_INFO_GET
+ * @a1-4: 32-bit words access to the UUID data
+diff --git a/drivers/firmware/arm-ffa/core.c b/drivers/firmware/arm-ffa/core.c
+index 41c7b96e68..caba10caae 100644
+--- a/drivers/firmware/arm-ffa/core.c
++++ b/drivers/firmware/arm-ffa/core.c
+@@ -1101,6 +1101,7 @@ static int __ffa_runtime ffa_msg_send_direct_req(u16 dst_part_id, struct ffa_sen
+ return ffa_to_std_errno(ffa_errno);
+ }
+
++#if !CONFIG_IS_ENABLED(SANDBOX_FFA)
+ /**
+ * __arm_ffa_fn_smc - SMC wrapper
+ * @args: FF-A ABI arguments to be copied to Xn registers
+@@ -1114,6 +1115,7 @@ void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+ {
+ arm_smccc_1_2_smc(&args, res);
+ }
++#endif
+
+ /**
+ * ffa_set_smc_conduit - Set the SMC conduit
+@@ -1127,7 +1129,12 @@ void __ffa_runtime __arm_ffa_fn_smc(ffa_value_t args, ffa_value_t *res)
+ */
+ static int ffa_set_smc_conduit(void)
+ {
+- ffa_priv_data->invoke_ffa_fn = __arm_ffa_fn_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_fn_smc;
++#endif
+
+ if (!ffa_priv_data->invoke_ffa_fn) {
+ ffa_err("failure to set the invoke function");
+@@ -1304,17 +1311,18 @@ struct ffa_prvdata **ffa_bus_prvdata_get(void)
+ }
+
+ /**
+- * 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).
+ *
+ * When the bus was already discovered successfully the discovery will not run again.
+ *
+ * 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:
+@@ -1325,9 +1333,15 @@ int ffa_bus_discover(void)
+ {
+ int ret = 0;
+
+- if (!ffa_priv_data)
++ if (!ffa_priv_data) {
+ ret = ffa_device_get();
+
++#if CONFIG_IS_ENABLED(SANDBOX_FFA)
++ if (ret == 0)
++ ret = sandbox_ffa_device_get();
++#endif
++ }
++
+ return ret;
+ }
+
+diff --git a/drivers/firmware/arm-ffa/sandbox.c b/drivers/firmware/arm-ffa/sandbox.c
+new file mode 100644
+index 0000000000..16e1fdc809
+--- /dev/null
++++ b/drivers/firmware/arm-ffa/sandbox.c
+@@ -0,0 +1,659 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@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 = 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,
++ }
++ }
++
++};
++
++/*
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++int sandbox_ffa_device_get(void)
++{
++ int ret;
++
++ if (sandbox_ffa_priv_data.dev)
++ return 0;
++
++ 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 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 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;
++
++ /* x1-x7 MBZ */
++ memset(FFA_X1X7_MBZ_REG_START, 0, FFA_X1X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_id_get)
++{
++ res->a0 = FFA_SMC_32(FFA_SUCCESS);
++ res->a1 = 0;
++
++ sandbox_ffa_priv_data.id = NS_PHYS_ENDPOINT_ID;
++ res->a2 = sandbox_ffa_priv_data.id;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_features)
++{
++ 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(unsigned long));
++ } else {
++ res->a0 = FFA_SMC_32(FFA_ERROR);
++ res->a2 = FFA_ERR_STAT_NOT_SUPPORTED;
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START,
++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++ ffa_err("[Sandbox] FF-A interface 0x%lx not implemented", pargs->a1);
++ }
++
++ res->a1 = 0;
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 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_SMC_32(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 (!pargs->a1 && !pargs->a2 && !pargs->a3 && !pargs->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_SMC_32(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 (pargs->a1 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a1 &&
++ pargs->a2 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a2 &&
++ pargs->a3 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.a3 &&
++ pargs->a4 == sandbox_ffa_priv_data.partitions.descs[descs_cnt].sp_uuid.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_SMC_32(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 {
++ /* Unrecognized UUID */
++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
++ }
++
++cleanup:
++
++ ffa_err("[Sandbox] FFA_PARTITION_INFO_GET (%ld)", res->a2);
++
++ res->a1 = 0;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START, 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_rxtx_map)
++{
++ res->a0 = FFA_SMC_32(FFA_ERROR);
++
++ if (sandbox_ffa_priv_data.pair.txbuf && sandbox_ffa_priv_data.pair.rxbuf) {
++ res->a2 = FFA_ERR_STAT_DENIED;
++ goto feedback;
++ }
++
++ if (pargs->a3 >= RXTX_BUFFERS_MIN_PAGES && pargs->a1 && pargs->a2) {
++ sandbox_ffa_priv_data.pair.txbuf = pargs->a1;
++ sandbox_ffa_priv_data.pair.rxbuf = pargs->a2;
++ sandbox_ffa_priv_data.pair_info.rxtx_buf_size = pargs->a3;
++ sandbox_ffa_priv_data.pair_info.rxbuf_mapped = 1;
++ res->a0 = FFA_SMC_32(FFA_SUCCESS);
++ res->a2 = 0;
++ goto feedback;
++ }
++
++ if (!pargs->a1 || !pargs->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;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START,
++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_rxtx_unmap)
++{
++ res->a0 = FFA_SMC_32(FFA_ERROR);
++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
++
++ if (GET_NS_PHYS_ENDPOINT_ID(pargs->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_SMC_32(FFA_SUCCESS);
++ res->a2 = 0;
++ goto feedback;
++ }
++
++ ffa_err("[Sandbox] No buffer pair registered on behalf of the caller");
++
++feedback:
++
++ res->a1 = 0;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START,
++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_rx_release)
++{
++ if (!sandbox_ffa_priv_data.pair_info.rxbuf_owned) {
++ res->a0 = FFA_SMC_32(FFA_ERROR);
++ res->a2 = FFA_ERR_STAT_DENIED;
++ } else {
++ sandbox_ffa_priv_data.pair_info.rxbuf_owned = 0;
++ res->a0 = FFA_SMC_32(FFA_SUCCESS);
++ res->a2 = 0;
++ }
++
++ res->a1 = 0;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START,
++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++}
++
++/**
++ * 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
++ */
++static 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.
++ * In case of success FFA_MSG_SEND_DIRECT_RESP is returned with default pattern data (0xff).
++ *
++ * Return:
++ *
++ * 0 on success. Otherwise, failure
++ */
++SANDBOX_SMC_FFA_ABI(ffa_msg_send_direct_req)
++{
++ u16 part_id;
++
++ part_id = GET_DST_SP_ID(pargs->a1);
++
++ if ((GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != sandbox_ffa_priv_data.id) ||
++ !sandbox_ffa_sp_valid(part_id) ||
++ pargs->a2) {
++ res->a0 = FFA_SMC_32(FFA_ERROR);
++ res->a1 = 0;
++ res->a2 = FFA_ERR_STAT_INVALID_PARAMETERS;
++
++ /* x3-x7 MBZ */
++ memset(FFA_X3_MBZ_REG_START,
++ 0, FFA_X3X7_MBZ_CNT * sizeof(unsigned long));
++
++ return 0;
++ }
++
++ res->a0 = FFA_SMC_64(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 = 0xffffffffffffffff;
++ res->a4 = 0xffffffffffffffff;
++ res->a5 = 0xffffffffffffffff;
++ res->a6 = 0xffffffffffffffff;
++ res->a7 = 0xffffffffffffffff;
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++static int sandbox_ffa_get_prv_data(struct ffa_sandbox_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_bus_prvdata_get());
++ *((struct sandbox_ffa_prvdata **)func_data->data1) = &sandbox_ffa_priv_data;
++
++ return 0;
++}
++
++/**
++ * 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:
++ *
++ * 0 on success. Otherwise, failure
++ */
++static int sandbox_ffa_get_rxbuf_flags(u32 queried_func_id, struct ffa_sandbox_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 0;
++ case FFA_RX_RELEASE:
++ *((u8 *)func_data->data0) = sandbox_ffa_priv_data.pair_info.rxbuf_owned;
++ return 0;
++ default:
++ ffa_err("[Sandbox] The querried FF-A interface flag (%d) undefined",
++ queried_func_id);
++ return -EINVAL;
++ }
++}
++
++/**
++ * sandbox_ffa_query_core_state - 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
++ *
++ * 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)
++{
++ 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_arm_ffa_smccc_smc - FF-A SMC call emulation
++ * @args: the SMC call arguments
++ * @res: the SMC call returned data
++ *
++ * 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:
++ *
++ * 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;
++
++ switch (args.a0) {
++ case FFA_SMC_32(FFA_VERSION):
++ ret = sandbox_ffa_version(&args, res);
++ break;
++ case FFA_SMC_32(FFA_PARTITION_INFO_GET):
++ ret = sandbox_ffa_partition_info_get(&args, res);
++ break;
++ case FFA_SMC_32(FFA_RXTX_UNMAP):
++ ret = sandbox_ffa_rxtx_unmap(&args, res);
++ break;
++ case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ):
++ ret = sandbox_ffa_msg_send_direct_req(&args, res);
++ break;
++ case FFA_SMC_32(FFA_ID_GET):
++ ret = sandbox_ffa_id_get(&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(&args, res);
++ break;
++ case FFA_SMC_32(FFA_RX_RELEASE):
++ ret = sandbox_ffa_rx_release(&args, res);
++ break;
++ default:
++ ffa_err("[Sandbox] Undefined FF-A interface (0x%lx)", args.a0);
++ }
++
++ if (ret != 0)
++ ffa_err("[Sandbox] FF-A ABI internal failure (%d)", ret);
++}
++
++/**
++ * sandbox_ffa_probe - The driver probe function
++ * @dev: the sandbox_arm_ffa device
++ *
++ * Return:
++ *
++ * 0 on success. Otherwise, failure
++ */
++static int sandbox_ffa_probe(struct udevice *dev)
++{
++ return 0;
++}
++
++/**
++ * sandbox_ffa_remove - The driver remove function
++ * @dev: the sandbox_arm_ffa device
++ *
++ * Return:
++ *
++ * 0 on success. Otherwise, failure
++ */
++static int sandbox_ffa_remove(struct udevice *dev)
++{
++ ffa_info("[Sandbox] removing the device");
++ memset(&sandbox_ffa_priv_data, 0, sizeof(sandbox_ffa_priv_data));
++ return 0;
++}
++
++/**
++ * 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,
++ .remove = sandbox_ffa_remove,
++};
+diff --git a/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h
+new file mode 100644
+index 0000000000..4db57f5092
+--- /dev/null
++++ b/drivers/firmware/arm-ffa/sandbox_arm_ffa_prv.h
+@@ -0,0 +1,144 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#ifndef __SANDBOX_ARM_FFA_PRV_H
++#define __SANDBOX_ARM_FFA_PRV_H
++
++#include "arm_ffa_prv.h"
++#include <sandbox_arm_ffa.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"
++
++/* FF-A ABIs internal error codes (as defined by the spec) */
++
++#define FFA_ERR_STAT_NOT_SUPPORTED -1
++#define FFA_ERR_STAT_INVALID_PARAMETERS -2
++#define FFA_ERR_STAT_NO_MEMORY -3
++#define FFA_ERR_STAT_BUSY -4
++#define FFA_ERR_STAT_DENIED -6
++
++/* Providing Arm SMCCC declarations to sandbox */
++
++#define ARM_SMCCC_FAST_CALL 1UL
++#define ARM_SMCCC_OWNER_STANDARD 4
++#define ARM_SMCCC_SMC_32 0
++#define ARM_SMCCC_SMC_64 1
++#define ARM_SMCCC_TYPE_SHIFT 31
++#define ARM_SMCCC_CALL_CONV_SHIFT 30
++#define ARM_SMCCC_OWNER_MASK 0x3F
++#define ARM_SMCCC_OWNER_SHIFT 24
++#define ARM_SMCCC_FUNC_MASK 0xFFFF
++
++#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
++ (((type) << ARM_SMCCC_TYPE_SHIFT) | \
++ ((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
++ (((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
++ ((func_num) & ARM_SMCCC_FUNC_MASK))
++
++/* 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)
++
++/* secure partitions count */
++#define SANDBOX_PARTITIONS_CNT (4)
++
++/* 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: 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;
++};
++
++#define SANDBOX_SMC_FFA_ABI(ffabi) static int sandbox_##ffabi(ffa_value_t *pargs, ffa_value_t *res)
++
++#endif
+diff --git a/include/arm_ffa.h b/include/arm_ffa.h
+index f17b100497..665413a0c5 100644
+--- a/include/arm_ffa.h
++++ b/include/arm_ffa.h
+@@ -111,7 +111,7 @@ struct ffa_bus_ops {
+ const struct ffa_bus_ops * __ffa_runtime ffa_bus_ops_get(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);
+
+diff --git a/include/sandbox_arm_ffa.h b/include/sandbox_arm_ffa.h
+new file mode 100644
+index 0000000000..d5df16f282
+--- /dev/null
++++ b/include/sandbox_arm_ffa.h
+@@ -0,0 +1,91 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#ifndef __SANDBOX_ARM_FFA_H
++#define __SANDBOX_ARM_FFA_H
++
++#include <arm_ffa.h>
++
++/**
++ * struct sandbox_smccc_1_2_regs - Arguments for or Results from emulated SMC call
++ * @a0-a17 argument values from registers 0 to 17
++ */
++struct sandbox_smccc_1_2_regs {
++ unsigned long a0;
++ unsigned long a1;
++ unsigned long a2;
++ unsigned long a3;
++ unsigned long a4;
++ unsigned long a5;
++ unsigned long a6;
++ unsigned long a7;
++ unsigned long a8;
++ unsigned long a9;
++ unsigned long a10;
++ unsigned long a11;
++ unsigned long a12;
++ unsigned long a13;
++ unsigned long a14;
++ unsigned long a15;
++ unsigned long a16;
++ unsigned long a17;
++};
++
++typedef struct sandbox_smccc_1_2_regs ffa_value_t;
++
++/* UUIDs of services supported by the sandbox driver */
++#define SANDBOX_SERVICE1_UUID "ed32d533-4209-99e6-2d72-cdd998a79cc0"
++#define SANDBOX_SERVICE2_UUID "ed32d544-4209-99e6-2d72-cdd998a79cc0"
++#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"
++
++#define SANDBOX_SP_COUNT_PER_VALID_SERVICE 2
++
++/**
++ * struct ffa_sandbox_data - generic data structure used to exchange
++ * data between test cases and the sandbox driver
++ * @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
++ *
++ * Using this structure sandbox test cases can pass various types of data with different sizes.
++ */
++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 driver public functions
++ */
++
++/**
++ * sandbox_ffa_query_core_state - Queries the status of FF-A ABIs
++ */
++int sandbox_ffa_query_core_state(u32 queried_func_id, struct ffa_sandbox_data *func_data);
++
++/**
++ * sandbox_ffa_get_device - create, bind and probe the sandbox_arm_ffa device
++ */
++int sandbox_ffa_device_get(void);
++
++/**
++ * sandbox_arm_ffa_smccc_smc - FF-A SMC call emulation
++ */
++void sandbox_arm_ffa_smccc_smc(ffa_value_t args, ffa_value_t *res);
++
++#endif
+diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
+index 0ec002ac8b..8fa9a58d76 100644
+--- a/lib/efi_loader/efi_boottime.c
++++ b/lib/efi_loader/efi_boottime.c
+@@ -2177,7 +2177,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
+ dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
+ }
+
+-#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT)
++#if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) && !CONFIG_IS_ENABLED(SANDBOX_FFA)
+ /* unmap FF-A RX/TX buffers */
+ if (ffa_bus_ops_get()->rxtx_unmap())
+ debug("[efi_boottime][ERROR]: can not unmap FF-A RX/TX buffers\n");
+--
+2.17.1
+