| From 4f104ef6804ffd6483d166840d113630be85edb0 Mon Sep 17 00:00:00 2001 |
| From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| Date: Mon, 17 Jul 2023 15:18:58 +0100 |
| Subject: [PATCH 06/33] FF-A v15: arm_ffa: introduce sandbox FF-A support |
| |
| 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.elkhlifi@arm.com> |
| Reviewed-by: Simon Glass <sjg@chromium.org> |
| Upstream-Status: Submitted [cover letter: https://lore.kernel.org/all/20230713132847.176000-1-abdellatif.elkhlifi@arm.com/] |
| --- |
| MAINTAINERS | 3 +- |
| arch/sandbox/dts/sandbox.dtsi | 9 + |
| arch/sandbox/dts/test.dts | 9 + |
| arch/sandbox/include/asm/sandbox_arm_ffa.h | 72 ++ |
| .../include/asm/sandbox_arm_ffa_priv.h | 121 +++ |
| configs/sandbox64_defconfig | 2 + |
| configs/sandbox_defconfig | 2 + |
| doc/arch/arm64.ffa.rst | 19 +- |
| 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 | 720 ++++++++++++++++++ |
| .../firmware/arm-ffa/sandbox_arm_ffa_priv.h | 14 - |
| drivers/firmware/arm-ffa/sandbox_ffa.c | 110 +++ |
| include/dm/uclass-id.h | 1 + |
| 15 files changed, 1084 insertions(+), 22 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 4ae82229fc..679a3acdd8 100644 |
| --- a/MAINTAINERS |
| +++ b/MAINTAINERS |
| @@ -269,12 +269,13 @@ F: configs/cortina_presidio-asic-pnand_defconfig |
| ARM FF-A |
| M: Abdellatif El Khlifi <abdellatif.elkhlifi@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 <sbabic@denx.de> |
| diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi |
| index 30a305c4d2..94a08814b8 100644 |
| --- a/arch/sandbox/dts/sandbox.dtsi |
| +++ b/arch/sandbox/dts/sandbox.dtsi |
| @@ -445,6 +445,15 @@ |
| 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 ff9f9222e6..c6807ee031 100644 |
| --- a/arch/sandbox/dts/test.dts |
| +++ b/arch/sandbox/dts/test.dts |
| @@ -1820,6 +1820,15 @@ |
| extcon { |
| compatible = "sandbox,extcon"; |
| }; |
| + |
| + 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..be2790f496 |
| --- /dev/null |
| +++ b/arch/sandbox/include/asm/sandbox_arm_ffa.h |
| @@ -0,0 +1,72 @@ |
| +/* SPDX-License-Identifier: GPL-2.0+ */ |
| +/* |
| + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> |
| + * |
| + * Authors: |
| + * Abdellatif El Khlifi <abdellatif.elkhlifi@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_query_ffa_emul_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 |
| + * |
| + * Query the status of FF-A ABI specified in the input argument. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +int sandbox_query_ffa_emul_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..b0881822d7 |
| --- /dev/null |
| +++ b/arch/sandbox/include/asm/sandbox_arm_ffa_priv.h |
| @@ -0,0 +1,121 @@ |
| +/* SPDX-License-Identifier: GPL-2.0+ */ |
| +/* |
| + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> |
| + * |
| + * Authors: |
| + * Abdellatif El Khlifi <abdellatif.elkhlifi@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; |
| +}; |
| + |
| +/** |
| + * 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 98b3e0cda4..2db69b8e52 100644 |
| --- a/configs/sandbox64_defconfig |
| +++ b/configs/sandbox64_defconfig |
| @@ -260,3 +260,5 @@ CONFIG_FWU_MULTI_BANK_UPDATE=y |
| CONFIG_UNIT_TEST=y |
| CONFIG_UT_TIME=y |
| CONFIG_UT_DM=y |
| +CONFIG_NVMXIP_QSPI=y |
| +CONFIG_ARM_FFA_TRANSPORT=y |
| diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig |
| index 1ec44d5b33..f77733377d 100644 |
| --- a/configs/sandbox_defconfig |
| +++ b/configs/sandbox_defconfig |
| @@ -344,3 +344,5 @@ CONFIG_TEST_FDTDEC=y |
| CONFIG_UNIT_TEST=y |
| CONFIG_UT_TIME=y |
| CONFIG_UT_DM=y |
| +CONFIG_CMD_2048=y |
| +CONFIG_ARM_FFA_TRANSPORT=y |
| diff --git a/doc/arch/arm64.ffa.rst b/doc/arch/arm64.ffa.rst |
| index aefd527447..b7c754fa3d 100644 |
| --- a/doc/arch/arm64.ffa.rst |
| +++ b/doc/arch/arm64.ffa.rst |
| @@ -33,6 +33,10 @@ The U-Boot FF-A support provides the following parts: |
| |
| - A Uclass driver providing generic FF-A 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 |
| ------------------------------------------- |
| @@ -62,6 +66,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 |
| --------------------------------------- |
| @@ -98,10 +103,8 @@ architecture features including FF-A bus. |
| |
| Class Index Probed Driver Name |
| ----------------------------------------------------------- |
| - ... |
| firmware 0 [ + ] psci |-- psci |
| ffa 0 [ ] arm_ffa | `-- arm_ffa |
| - ... |
| |
| The PSCI driver is bound to the PSCI device and when probed it tries to discover |
| the architecture features by calling a callback the features drivers provide. |
| @@ -205,6 +208,18 @@ The following features are provided: |
| |
| - FF-A bus can be compiled and used without EFI |
| |
| +Relationship between the sandbox emulator and the FF-A device |
| +--------------------------------------------------------------- |
| + |
| +:: |
| + |
| + => dm tree |
| + |
| + Class Index Probed Driver Name |
| + ----------------------------------------------------------- |
| + ffa_emul 0 [ + ] sandbox_ffa_emul `-- arm-ffa-emul |
| + ffa 0 [ ] sandbox_arm_ffa `-- sandbox-arm-ffa |
| + |
| The armffa command |
| ----------------------------------- |
| |
| diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst |
| index 77ca6bc4cc..a3631de749 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.elkhlifi@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..5562bbaac3 |
| --- /dev/null |
| +++ b/drivers/firmware/arm-ffa/ffa-emul-uclass.c |
| @@ -0,0 +1,720 @@ |
| +// SPDX-License-Identifier: GPL-2.0+ |
| +/* |
| + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> |
| + * |
| + * Authors: |
| + * Abdellatif El Khlifi <abdellatif.elkhlifi@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_SP3_ID, .exec_ctxt = 0x7687, .properties = 0x23325621 }, |
| + .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_SP2_ID, .exec_ctxt = 0x9587, .properties = 0x45325621 }, |
| + .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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_VERSION FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| + |
| +static int sandbox_ffa_version(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_ID_GET FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_id_get(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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 |
| + * |
| + * Emulate 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("FF-A interface %lx not implemented\n", pargs->a1); |
| + |
| + return ffa_to_std_errmap[NOT_SUPPORTED]; |
| +} |
| + |
| +/** |
| + * sandbox_ffa_partition_info_get() - Emulated FFA_PARTITION_INFO_GET handler |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_PARTITION_INFO_GET FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_partition_info_get(struct udevice *emul, 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(emul); |
| + |
| + 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_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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_RXTX_MAP FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_rxtx_map(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + int ret; |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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("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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_RXTX_UNMAP FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_rxtx_unmap(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + int ret; |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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("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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate FFA_RX_RELEASE FF-A function. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_rx_release(struct udevice *emul, ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + int ret; |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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() - Check SP validity |
| + * @emul: The sandbox FF-A emulator device |
| + * @part_id: partition ID to check |
| + * |
| + * Search the input ID in the descriptors table. |
| + * |
| + * Return: |
| + * |
| + * 1 on success (Partition found). Otherwise, failure |
| + */ |
| +static int sandbox_ffa_sp_valid(struct udevice *emul, u16 part_id) |
| +{ |
| + u32 descs_cnt; |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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 |
| + * @emul: The sandbox FF-A emulator device |
| + * @pargs: The SMC call input arguments a0-a7 |
| + * @res: The SMC return data |
| + * |
| + * Emulate 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 *emul, |
| + ffa_value_t *pargs, ffa_value_t *res) |
| +{ |
| + u16 part_id; |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + part_id = GET_DST_SP_ID(pargs->a1); |
| + |
| + if (GET_NS_PHYS_ENDPOINT_ID(pargs->a1) != priv->id || |
| + !sandbox_ffa_sp_valid(emul, 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() - Read the mapping/ownership flags |
| + * @emul: 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 |
| + * |
| + * Query 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 *emul, u32 queried_func_id, |
| + struct ffa_sandbox_data *func_data) |
| +{ |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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("The querried FF-A interface flag (%d) undefined\n", |
| + queried_func_id); |
| + return -EINVAL; |
| + } |
| +} |
| + |
| +/** |
| + * sandbox_ffa_get_fwk_version() - Return the FFA framework version |
| + * @emul: 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 *emul, struct ffa_sandbox_data *func_data) |
| +{ |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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 |
| + * @emul: 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 *emul, struct ffa_sandbox_data *func_data) |
| +{ |
| + struct sandbox_ffa_emul *priv = dev_get_priv(emul); |
| + |
| + 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_query_ffa_emul_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 |
| + * |
| + * Query the status of FF-A ABI specified in the input argument. |
| + * |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +int sandbox_query_ffa_emul_state(u32 queried_func_id, |
| + struct ffa_sandbox_data *func_data) |
| +{ |
| + struct udevice *emul; |
| + int ret; |
| + |
| + ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul); |
| + if (ret) { |
| + log_err("Cannot find FF-A emulator during querying state\n"); |
| + return ret; |
| + } |
| + |
| + switch (queried_func_id) { |
| + case FFA_RXTX_MAP: |
| + case FFA_RXTX_UNMAP: |
| + case FFA_RX_RELEASE: |
| + return sandbox_ffa_get_rxbuf_flags(emul, queried_func_id, func_data); |
| + case FFA_VERSION: |
| + return sandbox_ffa_get_fwk_version(emul, func_data); |
| + case FFA_PARTITION_INFO_GET: |
| + return sandbox_ffa_get_parts(emul, func_data); |
| + default: |
| + log_err("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 |
| + * |
| + * Emulate 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 *emul; |
| + |
| + ret = uclass_first_device_err(UCLASS_FFA_EMUL, &emul); |
| + if (ret) { |
| + log_err("Cannot find FF-A emulator during SMC emulation\n"); |
| + return; |
| + } |
| + |
| + switch (args->a0) { |
| + case FFA_SMC_32(FFA_VERSION): |
| + ret = sandbox_ffa_version(emul, args, res); |
| + break; |
| + case FFA_SMC_32(FFA_PARTITION_INFO_GET): |
| + ret = sandbox_ffa_partition_info_get(emul, args, res); |
| + break; |
| + case FFA_SMC_32(FFA_RXTX_UNMAP): |
| + ret = sandbox_ffa_rxtx_unmap(emul, args, res); |
| + break; |
| + case FFA_SMC_64(FFA_MSG_SEND_DIRECT_REQ): |
| + ret = sandbox_ffa_msg_send_direct_req(emul, args, res); |
| + break; |
| + case FFA_SMC_32(FFA_ID_GET): |
| + ret = sandbox_ffa_id_get(emul, 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(emul, args, res); |
| + break; |
| + case FFA_SMC_32(FFA_RX_RELEASE): |
| + ret = sandbox_ffa_rx_release(emul, args, res); |
| + break; |
| + default: |
| + log_err("Undefined FF-A interface (%lx)\n", |
| + args->a0); |
| + } |
| + |
| + if (ret != 0) |
| + log_err("FF-A ABI internal failure (%d)\n", ret); |
| +} |
| + |
| +/** |
| + * invoke_ffa_fn() - SMC wrapper |
| + * @args: FF-A ABI arguments to be copied to Xn registers |
| + * @res: FF-A ABI return data to be copied from Xn registers |
| + * |
| + * Calls the emulated SMC call. |
| + */ |
| +void invoke_ffa_fn(ffa_value_t args, ffa_value_t *res) |
| +{ |
| + sandbox_arm_ffa_smccc_smc(&args, res); |
| +} |
| + |
| +/** |
| + * ffa_emul_find() - Find the FF-A emulator |
| + * @dev: the sandbox FF-A device (sandbox-arm-ffa) |
| + * @emulp: the FF-A emulator device (sandbox-ffa-emul) |
| + * |
| + * Search 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) |
| +{ |
| + int ret; |
| + |
| + ret = uclass_first_device_err(UCLASS_FFA_EMUL, emulp); |
| + if (ret) { |
| + log_err("Cannot find FF-A emulator\n"); |
| + return ret; |
| + } |
| + |
| + log_info("FF-A emulator ready to use\n"); |
| + |
| + return 0; |
| +} |
| + |
| +UCLASS_DRIVER(ffa_emul) = { |
| + .name = "ffa_emul", |
| + .id = UCLASS_FFA_EMUL, |
| + .post_bind = dm_scan_fdt_dev, |
| +}; |
| + |
| +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, |
| + .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-office@arm.com> |
| - * |
| - * Authors: |
| - * Abdellatif El Khlifi <abdellatif.elkhlifi@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..ef9491ccea |
| --- /dev/null |
| +++ b/drivers/firmware/arm-ffa/sandbox_ffa.c |
| @@ -0,0 +1,110 @@ |
| +// SPDX-License-Identifier: GPL-2.0+ |
| +/* |
| + * Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> |
| + * |
| + * Authors: |
| + * Abdellatif El Khlifi <abdellatif.elkhlifi@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; |
| + |
| +/** |
| + * sandbox_ffa_discover() - perform sandbox FF-A discovery |
| + * @dev: The sandbox FF-A bus device |
| + * Try to discover the FF-A framework. Discovery is performed by |
| + * querying the FF-A framework version from secure world using the FFA_VERSION ABI. |
| + * Return: |
| + * |
| + * 0 on success. Otherwise, failure |
| + */ |
| +static int sandbox_ffa_discover(struct udevice *dev) |
| +{ |
| + int ret; |
| + struct udevice *emul; |
| + |
| + log_info("Emulated FF-A framework discovery\n"); |
| + |
| + ret = ffa_emul_find(dev, &emul); |
| + if (ret) { |
| + log_err("Cannot find FF-A emulator\n"); |
| + return ret; |
| + } |
| + |
| + ret = ffa_get_version_hdlr(dev); |
| + if (ret) |
| + return ret; |
| + |
| + return 0; |
| +} |
| + |
| +/** |
| + * sandbox_ffa_probe() - The sandbox FF-A driver probe function |
| + * @dev: the sandbox-arm-ffa device |
| + * Save the emulator device in uc_priv. |
| + * Return: |
| + * |
| + * 0 on success. |
| + */ |
| +static int sandbox_ffa_probe(struct udevice *dev) |
| +{ |
| + int ret; |
| + struct ffa_priv *uc_priv = dev_get_uclass_priv(dev); |
| + |
| + ret = uclass_first_device_err(UCLASS_FFA_EMUL, &uc_priv->emul); |
| + if (ret) { |
| + log_err("Cannot find FF-A emulator\n"); |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +/** |
| + * sandbox_ffa_bind() - The sandbox FF-A driver bind function |
| + * @dev: the sandbox-arm-ffa device |
| + * Try to discover the emulated FF-A bus. |
| + * Return: |
| + * |
| + * 0 on success. |
| + */ |
| +static int sandbox_ffa_bind(struct udevice *dev) |
| +{ |
| + int ret; |
| + |
| + ret = sandbox_ffa_discover(dev); |
| + if (ret) |
| + return ret; |
| + |
| + return 0; |
| +} |
| + |
| +/* 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, |
| + .bind = sandbox_ffa_bind, |
| + .probe = sandbox_ffa_probe, |
| + .ops = &sandbox_ffa_ops, |
| +}; |
| diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h |
| index 3c6af2e3d2..0432c95c9e 100644 |
| --- a/include/dm/uclass-id.h |
| +++ b/include/dm/uclass-id.h |
| @@ -63,6 +63,7 @@ enum uclass_id { |
| UCLASS_ETH_PHY, /* Ethernet PHY device */ |
| UCLASS_EXTCON, /* External Connector Class */ |
| 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 |
| |