| From 6d28dcdc36ad87b6987c7f920e06165c74eca59d Mon Sep 17 00:00:00 2001 |
| From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| Date: Tue, 29 Nov 2022 14:44:36 +0000 |
| Subject: [PATCH 06/25] 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. |
| |
| sandbox driver supports only 64-bit direct messaging. |
| |
| Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| Cc: Tom Rini <trini@konsulko.com> |
| Cc: Simon Glass <sjg@chromium.org> |
| Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org> |
| Cc: Jens Wiklander <jens.wiklander@linaro.org> |
| Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20221122131751.22747-1-abdellatif.elkhlifi@arm.com/] |
| |
| Changelog: |
| =============== |
| |
| 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 | 1 + |
| configs/sandbox64_defconfig | 2 + |
| configs/sandbox_defconfig | 2 + |
| doc/arch/sandbox.rst | 1 + |
| drivers/firmware/arm-ffa/Kconfig | 9 +- |
| drivers/firmware/arm-ffa/Makefile | 1 + |
| drivers/firmware/arm-ffa/arm_ffa_prv.h | 15 +- |
| drivers/firmware/arm-ffa/core.c | 22 +- |
| 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 +- |
| 13 files changed, 938 insertions(+), 13 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 d50bdddea8..23cebbd526 100644 |
| --- a/MAINTAINERS |
| +++ b/MAINTAINERS |
| @@ -255,6 +255,7 @@ F: cmd/armffa.c |
| F: doc/arch/arm64.ffa.rst |
| 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/configs/sandbox64_defconfig b/configs/sandbox64_defconfig |
| index 290d1506c2..36e6448968 100644 |
| --- a/configs/sandbox64_defconfig |
| +++ b/configs/sandbox64_defconfig |
| @@ -248,3 +248,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 ab5d3f19bf..8bf3848788 100644 |
| --- a/configs/sandbox_defconfig |
| +++ b/configs/sandbox_defconfig |
| @@ -328,3 +328,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 be4df89d23..b86f16d778 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 |
| @@ -29,3 +29,8 @@ config ARM_FFA_TRANSPORT |
| |
| For more details about the FF-A driver, please refer to doc/arch/arm64.ffa.rst |
| |
| +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 043a8915be..0d21d6b47a 100644 |
| --- a/drivers/firmware/arm-ffa/Makefile |
| +++ b/drivers/firmware/arm-ffa/Makefile |
| @@ -4,3 +4,4 @@ |
| # Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com. |
| |
| obj-y += arm-ffa-uclass.o core.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 4eea7dc036..bbc8b87069 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) |
| @@ -103,11 +113,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 0b1f8e6a07..560603b28b 100644 |
| --- a/drivers/firmware/arm-ffa/core.c |
| +++ b/drivers/firmware/arm-ffa/core.c |
| @@ -1072,6 +1072,7 @@ static int ffa_msg_send_direct_req(struct udevice *dev, u16 dst_part_id, |
| 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 |
| @@ -1085,6 +1086,7 @@ void __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 |
| @@ -1098,7 +1100,12 @@ void __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"); |
| @@ -1275,17 +1282,18 @@ struct ffa_prvdata *ffa_bus_prvdata_get(void) |
| } |
| |
| /** |
| - * ffa_bus_discover - discover FF-A bus and probe arm_ffa device |
| + * ffa_bus_discover - discover FF-A bus and probe arm_ffa and sandbox_arm_ffa devices |
| * @pdev: the address of a device pointer (to be filled when the arm_ffa bus device is created |
| * successfully) |
| * |
| * This function makes sure the FF-A bus is discoverable. |
| - * When probing succeeds FF-A discovery is done. The arm_ffa device is ready to use. |
| + * When probing succeeds FF-A discovery is done. The arm_ffa and sandbox_arm_ffa devices |
| + * are ready to use. |
| * |
| * 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: |
| @@ -1299,6 +1307,12 @@ int ffa_bus_discover(struct udevice **pdev) |
| if (!ffa_priv_data) { |
| ret = ffa_device_get(pdev); |
| |
| +#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..16f1ca926e |
| --- /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. 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 |
| + */ |
| +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 74b16174c2..b88904fe50 100644 |
| --- a/include/arm_ffa.h |
| +++ b/include/arm_ffa.h |
| @@ -90,7 +90,7 @@ struct ffa_bus_ops { |
| const struct ffa_bus_ops *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(struct udevice **pdev); |
| |
| 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 caa64028be..1099ccc800 100644 |
| --- a/lib/efi_loader/efi_boottime.c |
| +++ b/lib/efi_loader/efi_boottime.c |
| @@ -2185,7 +2185,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(NULL)) |
| log_err("Can't unmap FF-A RX/TX buffers\n"); |
| -- |
| 2.17.1 |
| |